arduino rgb led strip driver
[clinton/scratch.git] / arduino-rgb-led / gamma.py
diff --git a/arduino-rgb-led/gamma.py b/arduino-rgb-led/gamma.py
new file mode 100644 (file)
index 0000000..405b8b4
--- /dev/null
@@ -0,0 +1,69 @@
+# https://github.com/raplin/HexaWS2811/blob/master/gamma.py
+# Lookup table generator
+#
+# Really it's correcting for the eye's luminance response, it's not actually gamma correction (it's misnamed!)
+#
+# We're generating a set of 256-entry lookup tables which you use to (separately) convert the 8-bit R, G and B components of your color
+# into something you output, typically with an intelligent RGB LED such as a WS2812B; but a simple CPU-based PWM will give the same results (and benefit from this correction)
+# 
+# We generate several sets  (2,4,8...) of 256-entry tables so you can cycle through them, using a successive 8-bit lookup table each successive output frame.
+# This is 'temporal dithering', which aims to give you better color resolution at the dark end of the scale.
+# If you update at e.g. 100hz, try using two or three 'ditherBits' (i.e. 2^^2 or 2^^3=8 tables. The faster your update the more tables you can use
+# and you get better color resolution. More than 5 ditherbits is probably excessive, even 2 will help somewhat.
+#
+# If you get objectionable flickering when displaying low-intensity pixels, you should either update your leds faster or reduce ditherBits
+# 
+# 
+#
+fout=open("gamma.h","wt")
+
+#adjust me! Each extra bit doubles the table size 
+ditherBits=1
+
+ditherMSB=1<<(ditherBits-1)
+
+res="/* Dithered luminance correction table - autogenerated by gamma.py */\n#define DITHER_BITS %d\nconst prog_uchar PROGMEM gammaTable[]={" % ditherBits
+
+useRealLuminanceCalcuation=True # CIE 1931 formula
+
+finalAdjust=0  #set this to 1 if you want your values to start at one (1..255). This is a quirky request for FastLED users only
+
+for dither in range(1<<ditherBits):
+    out=[]
+
+    #reverse the low order bits so the dithering is less flickery
+    ditherValue=0
+    dread=1<<ditherBits
+    dout=1
+    for d in range(ditherBits):
+        dread>>=1
+        if dither & dread:
+            ditherValue|=dout
+        dout<<=1;
+    
+    ditherValue=(ditherValue<<(8-ditherBits))
+
+    for n in range(256):
+        if useRealLuminanceCalcuation:
+            # CIE 1931 
+            brightness=n/2.56
+            if brightness > 8:
+                pwmValue= pow( ((brightness + 16) / 116) , 3  )
+            else:
+                pwmValue = brightness / 903.3      
+            pwmValue*=256
+        else:
+            #use simple power 
+            pwmValue=pow(255,(n/256.0))-1
+        pwmValue=int(pwmValue*256)
+        pwmValue+=ditherValue
+        pwmValue=min(255, (pwmValue>>8)+finalAdjust)
+        out.append( pwmValue )
+    if dither:
+        res+=","
+    res+="\n\t"+(",".join([ "0x%x"%n for n in out]))  
+    
+res+="\n\t};\n"
+
+print >>fout,res
+fout.close()