diff --git a/code/main.py b/code/main.py new file mode 100644 index 0000000..4bee919 --- /dev/null +++ b/code/main.py @@ -0,0 +1,110 @@ +import machine +from machine import Pin, ADC +from neopixel import NeoPixel +from time import sleep + +machine.freq(240000000) # set the CPU frequency to 240 MHz + +PIXELPIN = Pin(20, Pin.OUT) +NUM_PIXELS = 16 + +ADC0 = ADC(Pin(26)) +ADC1 = ADC(Pin(27)) +ADC2 = ADC(Pin(28)) + + +def hsv_to_rgb(hsv) -> tuple[float, float, float]: + H, S, V = hsv + + h_i = int(H * 6) + f = H * 6 - h_i + + p = V * (1 - S) + q = V * (1 - S * f) + t = V * (1 - S * (1 - f)) + + if h_i == 0 or h_i == 6: + return (V, t, p) + if h_i == 1: + return (q, V, p) + if h_i == 2: + return (p, V, t) + if h_i == 3: + return (p, q, V) + if h_i == 4: + return (t, p, V) + # implicit case 5 + return (V, p, q) + + +def read_adc_float(adc: ADC) -> float: + value = adc.read_u16() + return value / 2**16 + + +def read_adc(adc: ADC) -> int: + lower_limit = 1024 + upper_limit = 1024 + + adc_range = 2**16 + + value = adc.read_u16() + + if value < lower_limit: + return 0 + if value > adc_range - upper_limit: + return 255 + + value -= lower_limit + + value = min(value, adc_range - lower_limit - upper_limit) + + return min(int(value / (adc_range - lower_limit - upper_limit) * 256), 255) + + +def float_to_u8(value: float) -> int: + return min(255, int(256 * value)) + + +def denoise(value: float, factor: float = 0.05) -> float: + """ + Rescales the range of the float from 0.0 to 1.0 to factor to 1-factor. + Values below factor and above 1-factor are set to 0.0 and 1.0 respecitvely. + """ + + if value < factor: + return 0.0 + if value > 1 - factor: + return 1.0 + + return max(0.0, min(1.0, (value - factor) / (1 - 2 * factor))) + + +np = NeoPixel(PIXELPIN, NUM_PIXELS, bpp=4) + +ww = 0.0 +hue = 0.0 +value = 0.0 + +dampening_factor = 0.25 +while True: + ww = (1.0 - dampening_factor) * ww + dampening_factor * read_adc_float(ADC0) + hue = (1.0 - dampening_factor) * hue + dampening_factor * read_adc_float(ADC1) + value = (1.0 - dampening_factor) * value + dampening_factor * read_adc_float(ADC2) + + hsv = (denoise(hue), 1.0, denoise(value)) + + (r, g, b) = hsv_to_rgb(hsv) + + for i in range(0, NUM_PIXELS): + np[i] = ( + float_to_u8(r), + float_to_u8(g), + float_to_u8(b), + float_to_u8(denoise(ww)), + ) + + np.write() + + print(float_to_u8(ww), float_to_u8(hue), float_to_u8(value)) + sleep(0.01)