+# Example code for [charlieplexed] GPIO Xmas Tree for \r
+# Raspberry Pi by Andrew Gale.\r
+\r
+import RPi.GPIO as GPIO\r
+import time\r
+\r
+# The tree connects to the 6 GPIO pins furthest away from the\r
+# corner of Raspberry Pi i.e. *physical* pin numbers 21-26 on\r
+# the model A or B and 35-40 on the B+.\r
+\r
+# Some Kickstarter supporters opted to receive a 'bi-colour'\r
+# LED as their stretch goal reward. This fits in the top\r
+# LED position (i.e. LED_0) but actually contains a second\r
+# LED that we shall call LED_7\r
+\r
+# Bicolour LED fitted or not?\r
+# bicolour_fitted = False # the default is False\r
+bicolour_fitted = True # the default is False\r
+\r
+# The time for which each LED is illuminated.\r
+# This is the place to tweak the brightness of the bicolour\r
+# LEDs by altering their illumination time.\r
+illumination_time_bicolour_green = 0.004 # the ON time for the bicolour green LED\r
+illumination_time_bicolour_red = 0.004 # the ON time for the bicolour red LED\r
+illumination_time_default = 0.001 # the ON time for all the other LEDs\r
+\r
+# The following constants will be configured by tree.setup()\r
+# but we will set them to -1 for now.\r
+A, B, C, D = -1, -1, -1, -1 # The four Charlieplexing nodes\r
+total_illumination_time = -1 # Time for one whole cycle\r
+\r
+# The following code to detect which version of Raspberry Pi\r
+# you are using is courtesy of Matt Hawkins at\r
+# http://www.raspberrypi-spy.co.uk\r
+\r
+def getrevision():\r
+ # Extract board revision from cpuinfo file\r
+ myrevision = "0000"\r
+ try:\r
+ f = open('/proc/cpuinfo','r')\r
+ for line in f:\r
+ if line[0:8]=='Revision':\r
+ length=len(line)\r
+ myrevision = line[11:length-1]\r
+ f.close()\r
+ except:\r
+ myrevision = "0000"\r
+ \r
+ return myrevision\r
+\r
+\r
+\r
+def single_led_on(n):\r
+ if (A==-1):\r
+ print "***********************************************"\r
+ print "** **"\r
+ print "** ERROR: you MUST call tree.setup() first!! **"\r
+ print "** **"\r
+ print "***********************************************"\r
+ raise Exception('You MUST call tree.setup() first!!')\r
+ \r
+ # First, set all the nodes to be input (effectively\r
+ # 'disconnecting' them from the Raspberry Pi) \r
+ GPIO.setup(A, GPIO.IN)\r
+ GPIO.setup(B, GPIO.IN)\r
+ GPIO.setup(C, GPIO.IN)\r
+ GPIO.setup(D, GPIO.IN)\r
+ GPIO.setup(A2, GPIO.IN)\r
+ GPIO.setup(B2, GPIO.IN)\r
+ GPIO.setup(C2, GPIO.IN)\r
+ GPIO.setup(D2, GPIO.IN)\r
+ \r
+ # Now determine which nodes are connected to the anode\r
+ # and cathode for this LED\r
+ if (n==1): anode, cathode = C, A\r
+ elif (n==2): anode, cathode = C, D\r
+ elif (n==4): anode, cathode = D, C\r
+ elif (n==8): anode, cathode = D, B\r
+ elif (n==16): anode, cathode = B, D\r
+ elif (n==32): anode, cathode = A, B\r
+ elif (n==64): anode, cathode = B, A\r
+ elif (n==128): anode, cathode = A, C\r
+ elif (n==(256+1)): anode, cathode = C2, A2\r
+ elif (n==(256+2)): anode, cathode = C2, D2\r
+ elif (n==(256+4)): anode, cathode = D2, C2\r
+ elif (n==(256+8)): anode, cathode = D2, B2\r
+ elif (n==(256+16)): anode, cathode = B2, D2\r
+ elif (n==(256+32)): anode, cathode = A2, B2\r
+ elif (n==(256+64)): anode, cathode = B2, A2\r
+ elif (n==(256+128)): anode, cathode = A2, C2\r
+ else: return # invalid LED number\r
+\r
+ # Configure the anode and cathode nodes to be outputs\r
+ GPIO.setup(anode, GPIO.OUT)\r
+ GPIO.setup(cathode, GPIO.OUT)\r
+ \r
+ # Make the anode high (+3.3v) and the cathode low (0v)\r
+ GPIO.output(anode, GPIO.HIGH)\r
+ GPIO.output(cathode, GPIO.LOW)\r
+ \r
+ \r
+def leds_on_and_wait(leds, wait_time):\r
+ # This routine is passed an 8-bit value (in the "leds"\r
+ # parameter) with one bit representing each LED. This routine\r
+ # checks each bit in turn and, if it's set to '1' then it\r
+ # turns the LED on for 0.001 seconds (or whatever is defined\r
+ # in the constants at the top). The whole routine\r
+ # loops around as many times as it can in the time specified\r
+ # in the "wait_time" parameter, thereby creating the illusion\r
+ # that all LEDs are on simultaneously (due to persistence\r
+ # of vision) when, in reality, only one is on at a time.\r
+ \r
+ # When used with a bicolour LED at the top of the tree, this\r
+ # routine is passed a 9-bit value.\r
+ # Bit 7 is for the red LED in the bicolour LED.\r
+ # Bit 8 is for the green LED in the bicolour LED.\r
+ # Bit 0: to maintain compatibility with code for a non-bicolour version of\r
+ # the tree, if bit 0 is set then we want the bicolour LED to light BOTH LEDs\r
+ # to mimic the yellow of the non-bicolour version of the tree.\r
+ \r
+ if (bicolour_fitted):\r
+ bicolour_leds = 0\r
+ if (leds & 1):\r
+ # bit 0 is set, so display bicolour as amber/yellow\r
+ #leds = (leds & 0b001111110) # preserve the 6 standard red LED bits\r
+ bicolour_leds |= (128+1) # enable the red and green bicolour LEDs\r
+ if (leds & 128):\r
+ # bit 7 is set so display bicolour as red\r
+ #leds = (leds & 0b001111110) # preserve the 6 standard red LED bits\r
+ bicolour_leds |= 128 # enable the red bicolour LEDs\r
+ if (leds & 256):\r
+ # bit 8 is set so display bicolour as green\r
+ #leds = (leds & 0b001111110) # preserve the 6 standard red LED bits\r
+ bicolour_leds |= 1 # enable the green bicolour LEDs\r
+ if (leds & 2**9):\r
+ # bit 9 is set, so display second bicolour as amber/yellow\r
+ #leds = (leds & 0b001111110) # preserve the 6 standard red LED bits\r
+ bicolour_leds |= (2**15+2**8) # enable the red and green bicolour LEDs\r
+ if (leds & 2**16):\r
+ # bit 16 is set so display bicolour as red\r
+ #leds = (leds & 0b001111110) # preserve the 6 standard red LED bits\r
+ bicolour_leds |= 2**15 # enable the red bicolour LEDs\r
+ if (leds & 2*17):\r
+ # bit 8 is set so display bicolour as green\r
+ #leds = (leds & 0b001111110) # preserve the 6 standard red LED bits\r
+ bicolour_leds |= 2**8 # enable the green bicolour LEDs\r
+ leds = (leds & 0b00111111001111110) # preserve the 6 standard red LED bits\r
+ leds = leds | bicolour_leds\r
+ print '{:017b}'.format(leds)\r
+ \r
+ for j in range(int(wait_time/total_illumination_time)):\r
+ for i in range(16):\r
+ single_led_on(leds & (1<<i))\r
+ \r
+ if (bicolour_fitted and (i==0 or i == 8)):\r
+ time.sleep(illumination_time_bicolour_green)\r
+ elif (bicolour_fitted and (i==7 or i == 16)):\r
+ time.sleep(illumination_time_bicolour_red)\r
+ else:\r
+ time.sleep(illumination_time_default)\r
+ \r
+ \r
+def all_leds_off():\r
+ single_led_on(0)\r
+ \r
+def setup():\r
+ global A\r
+ global B\r
+ global C\r
+ global D\r
+ global A2\r
+ global B2\r
+ global C2\r
+ global D2\r
+ global total_illumination_time\r
+ \r
+ GPIO.setmode(GPIO.BCM)\r
+ \r
+ # choose the correct GPIO pins depending on model\r
+ revision = getrevision()\r
+ print "** revision: ", revision\r
+ if ((revision == "0010") or (revision == "0012")):\r
+ print "Model B+ or A+"\r
+ A, B, C, D = 21, 19, 26, 20\r
+ else:\r
+ print "Other model, probably Model A or Model B"\r
+ print "Pi 2"\r
+ # A, B, C, D = 7, 9, 11, 8\r
+ A, B, C, D = 15, 3, 4, 14 # near corner\r
+ A2, B2, C2, D2 = 21, 19, 26, 20 # near USB\r
+\r
+ \r
+ if (bicolour_fitted):\r
+ total_illumination_time = 6 * illumination_time_default\r
+ total_illumination_time += illumination_time_bicolour_green\r
+ total_illumination_time += illumination_time_bicolour_red\r
+ else:\r
+ total_illumination_time = 8 * illumination_time_default\r
+ \r
+ #print "total_illumination_time: ", total_illumination_time\r
+ \r
+def cleanup():\r
+ GPIO.cleanup()\r
+ \r