User Tools

Site Tools


nsl_cylon

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

nsl_cylon [2013/08/13 12:13] (current)
Line 1: Line 1:
 +The end product of the first [[Eagle Class]]
 +
 +  * [[http://​storage.032.la/​NSL_Cylon.rar|NSL_Cylon Code]]
 +  * Code is also available on the [[http://​wiki.032.la/​nsl/​NSL_SVN_Server|NSL SVN]]  -  Under "/​032/​NSL_Cylon/"​
 +  * [[http://​batchpcb.com/​index.php/​Products/​48332|Buy the PCB at BatchPCB]]
 +
 +{{:​cylon.jpg?​600|thumb|center|cylon !!!}}
 +
 +[[FILE:​Cx_cylon_pov.jpg|600px|thumb|center|POV!]]
 +
 +http:<​nowiki>//</​nowiki>​farm7.static.flickr.com/​6020/​5988398941_9df936c29c_z.jpg
 +br
 +<​html>​
 +
 +<a href="​http:<​nowiki>//</​nowiki>​www.flickr.com/​photos/​51925658@N08/​5178009310/"​ title="​IMG_4838 by charlie _x, on Flickr"><​img src="​http:<​nowiki>//</​nowiki>​farm5.static.flickr.com/​4103/​5178009310_5460a434d9.jpg"​ width="​500"​ height="​333"​ alt="​IMG_4838"​ /></​a>​
 +</​html>​
 +
 +<​html>​
 +<object type="​application/​x-shockwave-flash"​ width="​400"​ height="​267" ​  ​data="​http:<​nowiki>//</​nowiki>​www.flickr.com/​apps/​video/​stewart.swf?​v=71377"​ classid="​clsid:​D27CDB6E-AE6D-11cf-96B8-444553540000">​ <param name="​flashvars"​ value="​intl_lang=en-us&​photo_secret=f0806a2b19&​photo_id=5147364504"></​param>​ <param name="​movie"​ value="​http:<​nowiki>//</​nowiki>​www.flickr.com/​apps/​video/​stewart.swf?​v=71377"></​param>​ <param name="​bgcolor"​ value="#​000000"></​param>​ <param name="​allowFullScreen"​ value="​true"></​param><​embed type="​application/​x-shockwave-flash"​ src="​http:<​nowiki>//</​nowiki>​www.flickr.com/​apps/​video/​stewart.swf?​v=71377"​ bgcolor="#​000000"​ allowfullscreen="​true"​ flashvars="​intl_lang=en-us&​photo_secret=f0806a2b19&​photo_id=5147364504"​ height="​267"​ width="​400"​ ></​embed></​object>​
 +</​html>​
 +
 +<​code>​
 + 
 +  - if 1
 +
 +/*
 +larson.c
 +The Larson Scanner ​
 +
 +Written by Windell Oskay, http:<​nowiki>//</​nowiki>​www.evilmadscientist.com/​
 +
 +<​code>​
 + ​Copyright 2009 Windell H. Oskay
 + ​Distributed under the terms of the GNU General Public License, please see below.</​code>​
 + 
 + 
 +
 +<​code>​
 + An avr-gcc program for the Atmel ATTiny2313  ​
 + ​Version 1.3   Last Modified: ​ 2/​8/​2009. ​
 + ​Written for Evil Mad Science Larson Scanner Kit, based on the "​ix"​ circuit board. ​
 + ​Improvements in v 1.3:
 + * EEPROM is used to *correctly* remember last speed & brightness mode.
 + ​Improvements in v 1.2:
 + * Skinny "​eye"​ mode.  Hold button at turn-on to try this mode.  To make it default,
 + ​solder jumper "Opt 1." ​ (If skinny mode is default, holding button will disable it temporarily.)
 + * EEPROM is used to remember last speed & brightness mode.</​code>​
 + 
 + 
 +<​code>​
 + More information about this project is at 
 + ​http://​www.evilmadscientist.com/​article.php/​larsonkit</​code>​
 + 
 + 
 + 
 +<​code>​
 + ​-------------------------------------------------
 + ​USAGE:​ How to compile and install</​code>​
 + 
 + 
 + 
 +<​code>​
 + A makefile is provided to compile and install this program using AVR-GCC and avrdude.
 + To use it, follow these steps:
 + 1. Update the header of the makefile as needed to reflect the type of AVR programmer that you use.
 + 2. Open a terminal window and move into the directory with this file and the makefile.  ​
 + 3. At the terminal enter
 + make clean   <​return>​
 + make all     <​return>​
 + make install <​return>​
 + 4. Make sure that avrdude does not report any errors. ​ If all goes well, the last few lines output by avrdude
 + ​should look something like this:
 + ​avrdude:​ verifying ...
 + ​avrdude:​ XXXX bytes of flash verified
 + ​avrdude:​ safemode: lfuse reads as 62
 + ​avrdude:​ safemode: hfuse reads as DF
 + ​avrdude:​ safemode: efuse reads as FF
 + ​avrdude:​ safemode: Fuses OK
 + ​avrdude done.  Thank you.</​code>​
 + 
 + 
 +<​code>​
 + If you a different programming environment,​ make sure that you copy over the fuse settings from the makefile.</​code>​
 + 
 + 
 +<​code>​
 + ​-------------------------------------------------
 + This code should be relatively straightforward,​ so not much documentation is provided. ​ If you'd like to ask 
 + ​questions,​ suggest improvements,​ or report success, please use the evilmadscientist forum:
 + ​http://​www.evilmadscientist.com/​forum/</​code>​
 + 
 + 
 +<​code>​
 + ​-------------------------------------------------</​code>​
 + 
 +  ​
 +  * /
 +
 +  - include <​avr/​io.h> ​
 +  - include <​avr/​eeprom.h> ​
 +  - include <​avr/​interrupt.h>​
 +  - include <​avr/​pgmspace.h>​
 +  - include <​util/​delay.h>​
 +
 +  - define shortdelay();​ \t\t\tasm("​nop\
 +\\t" \\
 +"nop\
 +\\t");
 +
 +  - define TIMER1_PRESCALE_1 \t\t(1)
 +  - define TIMER1_PRESCALE_8 \t\t(2)
 +  - define TIMER1_PRESCALE_64 \t\t(3)
 +  - define TIMER1_PRESCALE_256\t\t(4)
 +  - define TIMER1_PRESCALE_1024\t(5)
 +
 +uint16_t eepromWord __attribute__((section("​.eeprom"​)));​
 +
 +int main (void)
 +{
 +\tuint8_t LEDs[[9]]; // Storage for current LED values
 +\t
 +\tint8_t eyeLoc[[5]];​ // List of which LED has each role, leading edge through tail.
 +
 +\tuint8_t LEDBright[[4]] = {1u,​4u,​2u,​1u}; ​  // Relative brightness of scanning eye positions
 +\t
 +
 +
 +\tint8_t j, m;
 +\t
 +\tuint8_t position, loopcount, direction;
 +\tuint8_t ILED, RLED, MLED;
 +
 +\tuint8_t delaytime;
 +\t
 +\tuint8_t skinnyEye = 0;
 +\tuint8_t ​ pt, debounce, speedLevel;
 +\tuint8_t \tUpdateConfig;​
 +\tuint8_t BrightMode;
 +\tuint8_t debounce2, modeswitched;​
 +\t
 +\tuint8_t CycleCountLow;  ​
 +\tuint8_t LED0, LED1, LED2, LED3, LED4, LED5, LED6, LED7, LED8;
 +\t
 +\t//​Initialization routine: Clear watchdog timer-- this can prevent several things from going wrong.\t\t
 +\tMCUSR &= 0xF7;​\t\t//​Clear WDRF Flag
 +\tWDTCSR\t= 0x18;​\t\t//​Set stupid bits so we can clear timer...
 +\tWDTCSR\t= 0x00;
 +
 +\t//Data direction register: DDR's
 +\t//Port A: 0, 1 are inputs.\t
 +\t//Port B: 0-3 are outputs, B4 is an input.
 +\t//Port D: 1-6 are outputs, D0 is an input.
 +\t
 +\tDDRA = 0U;
 +\tDDRB = 15U;\t
 +\tDDRD = 126U;
 +\t
 +\tPORTA = 3;\t// Pull-up resistors enabled, PA0, PA1
 +\tPORTB = 16;\t// Pull-up resistor enabled, PA
 +\tPORTD = 0;
 +\t\t
 +<​code>​
 +  TCCR1B = (1 << WGM12) | TIMER1_PRESCALE_1;​
 +  OCR1A = (uint16_t)800;​
 +  TIMSK |= 1 << OCIE1A; ​  // Output Compare Interrupt Enable (timer 1, OCR1A) </​code>​
 +
 +\t/* Visualize outputs:
 + 
 +\t L to R:
 + 
 +\t D2 D3 D4 D5 D6 B0 B1 B2 B3\t
 +  ​
 +\t*/
 +\t
 +\t//​multiplexed = LowPower;\t
 + 
 +\tdebounce = 0; 
 +\tdebounce2 = 0;
 +\tloopcount = 254; 
 +\tdelaytime = 0;
 +\t
 +\tdirection = 0;
 +\tposition = 0;
 +\tspeedLevel = 0;  // Range: 1, 2, 3
 +\tBrightMode = 0;
 +\tCycleCountLow = 0;
 +\tUpdateConfig = 0;
 +\tmodeswitched = 0;
 +\t
 +\t
 +\tif ((PINA & 2) == 0)\t\t// Check if Jumper 1, at location PA1 is shorted
 +\t{  ​
 +\t\t// Optional place to do something. ​ :)
 +\t}
 +\t
 +\t
 +\t
 +\tif ((PINA & 1) == 0)\t\t// Check if Jumper 2, at location PA0 is shorted
 +\t{    ​
 +\t\tskinnyEye = 1; 
 +\t}\t
 +\t
 +\t
 +\tif ((PINB & 16) == 0)\t\t// Check if button pressed pressed down at turn-on
 +\t{\t\t
 +
 +\t//Toggle Skinnymode
 +\t\tif (skinnyEye)
 +\t\t\tskinnyEye = 0; 
 +\t\telse ​
 +\t\t\tskinnyEye = 1;
 +\t}
 +\t
 +\t
 +\t
 +\tif (skinnyEye){
 +\t\tLEDBright[[0]] = 0;
 +\t\tLEDBright[[1]] = 4;\t
 +\t\tLEDBright[[2]] = 1;
 +\t\tLEDBright[[3]] = 0;  ​
 +\t}
 +\t
 +\t
 +\t//Check EEPROM values:
 +\t
 +\tpt = (uint8_t) (eeprom_read_word(&​eepromWord)) ;
 +\tspeedLevel = pt >> 4;
 +\tBrightMode = pt & 1;
 +
 +\tif (pt == 0xFF)
 +\t{
 +\t\tBrightMode = 0;
 +\t}
 +\t
 +\t
 +\tif (speedLevel > 3)
 +\t\tspeedLevel = 1; 
 +\t
 +\tspeedLevel = 0;
 +
 +\tif ((speedLevel == 2) || (speedLevel == 3)) { 
 +\t\tdelaytime = 0;
 +\t} 
 +\telse ​
 +\t{   ​speedlevel = 1; 
 +\t\tdelaytime = 1;
 +\t}\t
 +\t
 +\t 
 +\t
 +for (;;)  <​nowiki>//</​nowiki>​ main loop
 +{
 +
 +
 +\tloopcount++;​
 +\t
 +\tif (loopcount > delaytime)
 +\t{
 +\t\tloopcount = 0;
 +\t\t
 +\t\tCycleCountLow++;​
 +\t\tif (CycleCountLow > 250)  ​
 +\t\t\tCycleCountLow = 0;
 +\t\t
 +\t\t
 +\t\tif (UpdateConfig){\t\t//​ need to save configuration byte to eeprom ​
 +\t\t\tif (CycleCountLow > 100) // Avoid burning EEPROM in event of flaky power connection resets
 +\t\t\t{
 +\t\t\t\t
 +\t\t\t\tUpdateConfig = 0;
 +\t\t\t\tpt = (speedLevel << 4) | (BrightMode & 1); 
 +\t\t\t\teeprom_write_word(&​eepromWord,​ (uint8_t) pt);\t
 +\t\t\t\t// Note: this function causes a momentary brightness glitch while it writes the EEPROM.
 +\t\t\t\t// We separate out this section to minimize the effect. ​
 +\t\t\t}
 +\t\t\t
 +\t\t}\t
 +
 +\t\t
 +\t\t
 +\tif ((PINB & 16) == 0)\t\t// Check for button press
 +\t{
 +\t\tdebounce2++;​
 +\t\t
 +\t\tif (debounce2 > 100)  ​
 +\t\t{   
 +\t\t\tif (modeswitched == 0)
 +\t\t\t{  ​
 +\t\t\t\tdebounce2 = 0;
 +\t\t\t\tUpdateConfig = 1;
 +
 +\t\t\t\tswitch( BrightMode ) {
 +\t\t\t\t
 +\t\t\t\t\t\tcase 0:
 +\t\t\t\t\t\t\tBrightMode++;​
 +\t\t\t\t\t\tcase 1: 
 +\t\t\t\t\t\t\tBrightMode++;​
 +\t\t\t\t\t\t\tbreak;​
 +\t\t\t\t\t\tcase 2:
 +\t\t\t\t\t\t//​ off
 +\t\t\t\t\t\t\t//​ switch on POV
 +\t\t\t\t\t\t\t//​ wrap
 +\t\t\t\t\t\t\tBrightMode++;​
 +\t\t\t\t\t\t\tbreak;​
 +
 +\t\t\t\t\t\tcase 3:
 +\t\t\t\t\t\t\t//​sei(); ​                // Set Enable Interrupts
 +\t\t\t\t\t\t\t//​ runs POV
 +\t\t\t\t\t\t\tBrightMode++;​
 +\t\t\t\t\t\t\tbreak;​
 +
 +\t\t\t\t\t\tcase 4:
 +\t\t\t\t\t\t\tsei(); ​                // Set Enable Interrupts
 +\t\t\t\t\t\t\tBrightMode++;​
 +\t\t\t\t\t\t\t//​ runs POV
 +\t\t\t\t\t\t\tbreak;​
 +\t\t\t\t\t\tcase 5:
 +\t\t\t\t\t\t\tcli(); ​                // Set Enable Interrupts
 +\t\t\t\t\t\t\t//​ runs POV
 +\t\t\t\t\t\t\tBrightMode =  0 ;
 +\t\t\t\t\t\t\tbreak;​
 +\t\t\t\t\t\t\t\t
 +\t\t\t\t\t\tdefault:​
 +\t\t\t\t\t\t\t//​ interrupts off and wrap
 +\t\t\t\t\t\t\tBrightMode= 0;
 +\t\t\t\t\t\t\tbreak;​
 +\t\t\t\t}
 +\t\t\t\t\t\t\t
 +\t\t\t\tmodeswitched = 1;
 +\t\t\t}
 +\t\t}
 +\t\telse {
 +\t\t\tdebounce = 1;\t\t// Flag that the button WAS pressed.
 +\t\t\tdebounce2++;​\t
 +\t\t}
 + 
 +\t}\t
 +\telse{ ​
 +\t\t
 +\t\tdebounce2 = 0;
 +\t\tmodeswitched = 0;
 +\t
 +\t\tif (debounce)
 +\t\t{ debounce = 0;
 +\t\t\tspeedLevel++;​
 +\t\t\tUpdateConfig = 1;
 +\t\t\t
 +\t\t\tif ((speedLevel == 2) || (speedLevel == 3)) { 
 +\t\t\t\tdelaytime = 0;
 +\t\t\t} ​
 +\t\t\telse ​
 +\t\t\t{ ​  ​speedlevel = 1; 
 +\t\t\t\tdelaytime = 1;
 +\t\t\t}
 +\t\t\t
 +\t\t\tdebounce = 0;
 +\t\t}
 +\t\t
 +\t\t\t}
 +\t    ​
 +\t\tposition++;​
 +\t\t
 +\t\tif (speedLevel == 3)
 +\t\t\tposition++;​
 +\t\t
 +\t if (position >= 128)\t//​was ​ == 128
 +\t {
 +\t\t position = 0;
 +\t\t 
 +\t  if (direction == 0)
 +\t\t  direction = 1;
 +\t  else
 +\t\t  direction = 0; 
 +\t }
 +\t
 +\t\t \t\t
 +\tif (direction == 0)  // Moving to right, as viewed from front.
 +\t{   
 +\t\tILED = (15+position) >> 4; 
 +\t\tRLED = (15+position) - (ILED << 4);
 +\t\tMLED = 15 - RLED; \t\t
 +\t\t}
 +<​code>​
 +   else </​code>​
 +\t{   
 +\t\tILED = (127 - position) >> 4;  ​
 +\t\tMLED = (127 - position) ​ - (ILED << 4);
 +\t\tRLED =  15 - MLED;\t
 +\t}
 +\t\t 
 +\t\tj = 0;
 +\t\twhile (j < 9) {
 +\t\t\tLEDs[[j]] = 0; 
 +\t\t\tj++;
 +\t\t}  ​
 +\t\t 
 +\t\tj = 0;
 +\t\twhile (j < 5) {
 +\t\t\t
 +\t\t\tif (direction == 0) 
 +\t\t\t ​  m = ILED + (2 - j);\t// e.g., eyeLoc[[0]] = ILED + 2; 
 +\t\t\telse
 +\t\t\t ​  m = ILED + (j - 2);  // e.g., eyeLoc[[0]] = ILED - 2;
 +\t\t\t
 +\t\t\tif (m > 8)
 +\t\t\t\tm -= (2 * (m - 8));
 +\t\t\t
 +\t\t\tif (m < 0)
 +\t\t\t\tm *= -1;
 +\t\t\t
 +\t\t\teyeLoc[[j]] = m;
 +\t\t\t
 +\t\t\tj++;
 +\t\t} 
 +\t\t  ​
 +\t\tj = 0;\t\t// For each of the eye parts...
 +\t\twhile (j < 4) {
 +\t\t\t
 +\t\t\tLEDs[eyeLoc[j]] ​  += LEDBright[[j]]*RLED;​\t\t\t
 +\t\t\tLEDs[eyeLoc[j+1]] += LEDBright[[j]]*MLED;​\t\t\t
 +\t\t\t ​
 +\t\t\tj++;
 +\t\t}  ​
 +\t
 +\t LED0 = LEDs[[0]];
 +<​code>​
 +     LED1 = LEDs[[1]];</​code>​
 +\t LED2 = LEDs[[2]];
 +\t LED3 = LEDs[[3]];
 +\t LED4 = LEDs[[4]];
 +\t LED5 = LEDs[[5]];
 +\t LED6 = LEDs[[6]];
 +\t LED7 = LEDs[[7]];
 +\t LED8 = LEDs[[8]];  ​
 +
 +\t}
 +
 +\tif ( BrightMode > 3 ) { 
 +\t\tcontinue;​
 +\t}
 +\t 
 +\tif (BrightMode == 0)
 +\t{\t\t//​multiplexing routine: each led is on (1/9) of the time. 
 +\t\t\t// ​ -> Use much less power.
 +\t\tj = 0;
 +\t\twhile (j < 60)\t\t// Truncate brightness at a max value (60) in the interest of speed.
 +\t\t{
 +\t\t  ​
 +\tif (LED0 > j) 
 +\t\tPORTD = 4; 
 +\t\t\telse\t
 +\t\t\tPORTD = 0;  ​
 +\t\t\t
 +\tif (LED1 > j) 
 +\t\tPORTD = 8;\t
 +\telse\t
 +\t\tPORTD = 0;\t 
 +\t\t\t
 +\tif (LED2 > j) 
 +\t\tPORTD = 16; 
 +\telse\t
 +\t\tPORTD = 0; 
 +\t\t\t
 +\tif (LED3 > j) 
 +\t\tPORTD = 32;\t
 +\telse\t
 +\t\tPORTD = 0;
 +\t\t\t
 +\tif (LED4 > j) 
 +\t\tPORTD = 64;
 +\telse\t
 +\t\tPORTD = 0;
 +\t\t  ​
 +\tif (LED5 > j) {
 +\t\tPORTB = 17;\t 
 +\t\tPORTD = 0;}
 +\t\t\telse\t{
 +\t\tPORTB = 16;
 +\tPORTD = 0;\t\t}
 +\t\t\t
 +\tif (LED6 > j) 
 +\t\tPORTB = 18;\t
 +\telse\t
 +\t\tPORTB = 16;
 +\t\t\t
 +\tif (LED7 > j) 
 +\t\tPORTB = 20;\t
 +\telse\t
 +\t\tPORTB = 16;
 +\t\t\t
 +\tif (LED8 > j) 
 +\t\tPORTB = 24;\t
 +\telse\t
 +\t\tPORTB = 16; 
 +\t\t 
 +\t\tj++;
 +<​nowiki>//</​nowiki>​\t\tif (speedLevel == 3)
 +<​nowiki>//</​nowiki>​\t\t\tj++;​
 +\t\t PORTB = 16; 
 +\t} 
 +\t 
 +\t} 
 +\t else 
 +\t {\t\t// full power routine
 +\t\t 
 +\t  j = 0;
 +\t  while (j < 70)
 +\t  {
 +\t  ​
 +\t  pt = 0;\t
 +\t  if (LED0 > j) 
 +\t  pt = 4; 
 +\t  if (LED1 > j) 
 +\t  pt |= 8;\t
 +\t  if (LED2 > j) 
 +\t  pt |= 16; 
 +\t  if (LED3 > j) 
 +\t  pt |= 32;​\t\t ​
 +\t  if (LED4 > j) 
 +\t  pt |= 64;
 +\t  ​
 +\t  PORTD = pt;
 +\t  shortdelay(); ​
 +\t  pt = 16;\t
 +\t  if (LED5 > j) 
 +\t  pt |= 1;\t
 +\t  if (LED6 > j) 
 +\t  pt |= 2;\t
 +\t  if (LED7 > j) 
 +\t  pt |= 4;\t
 +\t  if (LED8 > j) 
 +\t  pt |= 8;\t\t\t
 +\t  ​
 +\t  PORTB = pt;
 +\t  shortdelay(); ​
 +\t\t  ​
 +\t  j++;
 +<​nowiki>//</​nowiki>​\t ​ if (speedLevel == 3)
 +<​nowiki>//</​nowiki>​\t ​ j++;
 +\t  }
 +\t\t   
 +\t }
 +\t
 +\t 
 +<​nowiki>//</​nowiki>​Multiplexing routine: Each LED is on (1/9) of the time. 
 +<​nowiki>//</​nowiki> ​ -> Uses much less power.
 +   
 +\t}\t//End main loop
 +\treturn 0;
 +}
 +
 +
 +
 +  - define IS_BIT(a,​p) ​   (a&​(1<<​p)) ​   <​nowiki>//</​nowiki>​ test the a variable p bit
 +  - define SET_BIT(a,​p) a |=  (1<<​p) ​   <​nowiki>//</​nowiki>​ set in a the p bit
 +  - define CLR_BIT(a,​p) a &= ~(1<<​p) ​   <​nowiki>//</​nowiki>​ clear in a the p bit
 +
 +
 +  - define LED0 \t\t( 4 )//1
 +  - define LED1 \t\t( 3 )//2
 +  - define LED2 \t\t( 2 )//3
 +  - define LED3 \t\t( 1  )//4
 +  - define LED4 \t\t( 0 )//5
 +
 +<​nowiki>//</​nowiki>​ byte two
 +  - define LED5 \t\t( 3 )
 +  - define LED6 \t\t( 2 )
 +  - define LED7 \t\t( 1 )
 +  - define LED8 \t\t( 0 )
 +
 +void delay_ms( uint16_t milliseconds)
 +{
 +<​code>​
 +   for( ; milliseconds > 0; milliseconds--)
 +   {
 +      _delay_ms( 1);
 +   ​}</​code>​
 +
 +
 +
 +
 +<​nowiki>//</​nowiki>​ NSL Cylon
 +  - define B9__(x) ((x&​0x0000000FLU)?​LED0:​0) \\
 +<​code>​
 +               ​+((x&​0x000000F0LU)?​LED1:​0) \\
 +               ​+((x&​0x00000F00LU)?​LED2:​0) \\
 +               ​+((x&​0x0000F000LU)?​LED3:​0) \\
 +               ​+((x&​0x000F0000LU)?​LED4:​0) \\
 +               ​+((x&​0x00F00000LU)?​LED5:​0) \\
 +               ​+((x&​0x0F000000LU)?​LED6:​0) \\
 +               ​+((x&​0xF0000000LU)?​LED7:​0) \\
 +              +((x&​0xF00000000LU)?​LED8:​0) </​code>​
 +
 +  - define _B9(d) ((uint16_t)B9__(HEX__(d)))
 +
 +  - define B9(d) 0b##d
 +
 +
 +const static uint16_t large_image[[]] PROGMEM ​ ======
 +
 +
 +  - if 1
 +
 +\tB9(000000000), ​
 +\tB9(111111111), ​
 +\tB9(100000001), ​
 +\tB9(100000001), ​
 +\tB9(000000000), ​
 +\tB9(100000000), ​
 +\tB9(100000000), ​
 +\tB9(100000000), ​
 +\tB9(111111111), ​
 +\tB9(000000000), ​
 +\tB9(111110001), ​
 +\tB9(100010001), ​
 +\tB9(100010001), ​
 +\tB9(100011111), ​
 +\tB9(000000000), ​
 +\tB9(111111111), ​
 +\tB9(001000000), ​
 +\tB9(000111000), ​
 +\tB9(000000100), ​
 +\tB9(000000010), ​
 +\tB9(111111111), ​
 +\tB9(000000000), ​
 +\tB9(100000001), ​
 +\tB9(100000001), ​
 +\tB9(111111111), ​
 +\tB9(000000000), ​
 +\tB9(000000000), ​
 +\tB9(000000000), ​
 +
 +
 +<​nowiki>//</​nowiki>​ nullspace (backwards)
 +
 +\tB9(100010001), ​
 +\tB9(100010001), ​
 +\tB9(100010001), ​
 +\tB9(111111111), ​
 +\tB9(000000000), ​
 +\tB9(100000001), ​
 +\tB9(100000001), ​
 +\tB9(111111111), ​
 +\tB9(000000000), ​
 +\tB9(111111111), ​
 +\tB9(000010001), ​
 +
 +
 +\tB9(000010001), ​
 +\tB9(111111111), ​
 +\tB9(000000000), ​
 +\tB9(000011111), ​
 +\tB9(000010001), ​
 +\tB9(000010001), ​
 +\tB9(111111111), ​
 +\tB9(000000000), ​
 +\tB9(111110001), ​
 +\tB9(100010001), ​
 +\tB9(100010001), ​
 +\tB9(100011111), ​
 +\tB9(000000000), ​
 +\tB9(100000000), ​
 +\tB9(100000000), ​
 +\tB9(111111111), ​
 +\tB9(000000000), ​
 +\tB9(100000000), ​
 +\tB9(100000000), ​
 +\tB9(111111111), ​
 +\tB9(000000000), ​
 +\tB9(111111111), ​
 +\tB9(100000000), ​
 +\tB9(100000000), ​
 +\tB9(111111111), ​
 +\tB9(000000000), ​
 +\tB9(111111111), ​
 +\tB9(010000000), ​
 +\tB9(001110000), ​
 +\tB9(000001100), ​
 +\tB9(000000010), ​
 +\tB9(111111111), ​
 +
 +<​nowiki>//</​nowiki>​\t0,​0,​0,​0,​
 +
 +  - else
 +
 +<​nowiki>//</​nowiki>​ flickr
 +B9(010101010),​ B9(000000000), ​
 +B9(010101010),​ B9(000000000),​ B9(010101010),​ B9(101010101),​ B9(101010101),​ B9(101010101),​ B9(101010101), ​
 +B9(101010101),​ B9(010101010),​ B9(010101010),​ B9(010101010),​ B9(010101010),​ B9(010101010),​ B9(101010101),​ B9(101010101), ​
 +B9(101010101),​ B9(101010101),​ B9(101010101), ​
 +
 +<​nowiki>//</​nowiki>​
 +<​code>​
 + ​B9(000000000), ​
 + ​B9(000000000), ​
 + ​B9(101010101),​ B9(100000001), ​
 + ​B9(100000001),​ B9(000000000),​ B9(000000000),​ B9(100000000),​ B9(100000000),​ B9(100000000),​ B9(101010101),​ B9(000000000),​ B9(000000000),​ B9(101010001),​ B9(100010001),​ B9(100010001),​ B9(100010101),​ B9(000000000),​ B9(000000000),​ B9(101010101),​ B9(000000000),​ B9(001000000),​ B9(000010000),​ B9(000000100),​ B9(000000000),​ B9(101010101),​ B9(000000000),​ B9(000000000),​ B9(100000001),​ B9(100000001),​ B9(101010101), ​
 + ​B9(000000000), ​
 + ​B9(000000000),​
 + ​B9(000000000),​ B9(000000000),​ B9(000000000),​ B9(000000000),​ B9(000101010),​ B9(000100010),​ B9(000100010),​ B9(000100010), ​
 + ​B9(010101010),​ B9(000000000),​ B9(000000000),​ B9(000000010),​ B9(000100010),​ B9(000100010),​ B9(000100010),​ B9(010101010),​ B9(000000000),​ B9(000000000),​ B9(010101010),​ B9(000000000),​ B9(000001000),​ B9(000000000),​ B9(000100000),​ B9(000000000),​ B9(000001000),​ B9(000000000),​ B9(010101010),​ </​code>​
 +  - endif
 +  ​
 +\t0,0,0,0,
 +\t65535
 +};
 +
 +
 +<​nowiki>//</​nowiki>​ special pointer for reading from ROM memory
 +PGM_P largeimage_p PROGMEM = (PGM_P)large_image;​
 +
 +  - define NUM_ELEM(x) (sizeof (x) / sizeof (*(x)))
 +
 +<​nowiki>//</​nowiki>​ this function is called when timer1 compare matches OCR1A
 +
 +SIGNAL( SIG_TIMER1_COMPA ) {
 +
 +\tstatic uint8_t j = 0;
 +\tuint8_t tmpout;
 +
 +\tuint16_t tmp=0;
 +
 +<​nowiki>//</​nowiki>​reset counter
 +\tif (pgm_read_word(largeimage_p + j ) == 65535 ) {
 +\t\tj = 0;
 +\t}
 +
 +\ttmp = pgm_read_word(largeimage_p + j);
 +
 +\ttmpout = 0;
 +
 +\tif( IS_BIT(tmp,​0) ) SET_BIT(tmpout,​ LED0 ); 
 +\tif( IS_BIT(tmp,​1) ) SET_BIT(tmpout,​ LED1 ); 
 +\tif( IS_BIT(tmp,​2) ) SET_BIT(tmpout,​ LED2 ); 
 +\tif( IS_BIT(tmp,​3) ) SET_BIT(tmpout,​ LED3 ); 
 +
 +\tPORTB =  (  tmpout ​ ) >>1;
 +
 +\ttmpout = 0;
 +
 +\tif( IS_BIT(tmp,​4) ) SET_BIT(tmpout,​ LED0 ); 
 +\tif( IS_BIT(tmp,​5) ) SET_BIT(tmpout,​ LED5 ); 
 +\tif( IS_BIT(tmp,​6) ) SET_BIT(tmpout,​ LED6 ); 
 +\tif( IS_BIT(tmp,​7) ) SET_BIT(tmpout,​ LED7 ); 
 +\tif( IS_BIT(tmp,​8) ) SET_BIT(tmpout,​ LED8 ); 
 +
 +\tPORTD =  tmpout<<​2; ​
 +
 +<​nowiki>//</​nowiki>​ word
 +\tj+=2;
 +}
 +
 +  - else
 +/*
 +larsonextend.c
 +The Larson Scanner -- Alternative version to allow scanner to run off the edge of the board.
 + 
 +<​code>​
 + It simulates one LED at brightness 4, followed by one LED of brightness 1, that moves across
 + the nine pixels, disappearing off either end of the board, before returning to scan in the other direction.
 + There is no longer any overlap of these "​LEDs"​ at either end, but up to three LEDs may be lit at a time as
 + the head fades in and the tail fades out.
 + Also, some of the input and output values and pull-up resistors have been changed from the original program ​
 + in anticipation of future extensibility.
 + With the buttons linked between the units, it seems to be flakey, at best, to get an accurate button press
 + on multiple units at the same time, so that section is commented out below. ​ Change the speed in the variable
 + ​declarations as you see fit.  Also, since this program was originally written for a specific application
 + (a permanent installation in an enclosure), the unit was never really intended to change speeds. ​ I tried to
 + get it to work like the original, but couldn'​t. ​ Sorry, guys.</​code>​
 +
 +Original written by Windell Oskay, http:<​nowiki>//</​nowiki>​www.evilmadscientist.com/​
 +New alternative version written by John Breen III
 + 
 +<​code>​
 + ​Copyright 2009 Windell H. Oskay, 2010 John J. Breen III
 + ​Distributed under the terms of the GNU General Public License, please see below.</​code>​
 + 
 + 
 +
 +<​code>​
 + An avr-gcc program for the Atmel ATTiny2313  ​
 + Based on Version 1.1_alt1, written by Windell Oskay
 + ​Version 1.1   Last Modified: ​ 26-Sep-2010. ​
 + ​Written for Evil Mad Science Larson Scanner Kit, based on the "​ix"​ circuit board. </​code>​
 + 
 + 
 +<​code>​
 + More information about this project is at 
 + ​http://​www.evilmadscientist.com/​article.php/​larsonkit</​code>​
 + 
 + 
 + 
 +<​code>​
 + ​-------------------------------------------------
 + ​USAGE:​ How to compile and install</​code>​
 + 
 + 
 + 
 +<​code>​
 + A makefile is provided to compile and install this program using AVR-GCC and avrdude.
 + To use it, follow these steps:
 + 1. Update the header of the makefile as needed to reflect the type of AVR programmer that you use.
 + 2. Open a terminal window and move into the directory with this file and the makefile.  ​
 + 3. At the terminal enter
 + make clean   <​return>​
 + make all     <​return>​
 + make install <​return>​
 + 4. Make sure that avrdude does not report any errors. ​ If all goes well, the last few lines output by avrdude
 + ​should look something like this:
 + ​avrdude:​ verifying ...
 + ​avrdude:​ XXXX bytes of flash verified
 + ​avrdude:​ safemode: lfuse reads as 62
 + ​avrdude:​ safemode: hfuse reads as DF
 + ​avrdude:​ safemode: efuse reads as FF
 + ​avrdude:​ safemode: Fuses OK
 + ​avrdude done.  Thank you.</​code>​
 + 
 + 
 +<​code>​
 + If you a different programming environment,​ make sure that you copy over the fuse settings from the makefile.</​code>​
 + 
 + 
 +<​code>​
 + ​-------------------------------------------------
 + This code should be relatively straightforward,​ so not much documentation is provided. ​ If you'd like to ask 
 + ​questions,​ suggest improvements,​ or report success, please use the evilmadscientist forum:
 + ​http://​www.evilmadscientist.com/​forum/</​code>​
 + 
 + 
 +<​code>​
 + ​-------------------------------------------------</​code>​
 + 
 +  ​
 +  * /
 +
 +  - include <​avr/​io.h> ​
 +
 +  - define shortdelay();​ \t\t\tasm("​nop\
 +\\t" \\
 +"nop\
 +\\t");
 +
 +  ​
 +int main (void)
 +{
 +uint8_t LEDs[[9]]; // Storage for current LED values
 +uint8_t rightLED[[6]],​ leftLED[[6]];​ // Storage for initialization visualization LEDs
 +\t
 +int8_t eyeLoc[[5]];​ // List of which LED has each role, leading edge through tail.
 +
 +uint8_t LEDBright[[4]] = {4u,​2u,​1u,​1u}; ​  // Relative brightness of scanning eye positions, head through tail
 +
 +void delay_ms(uint8_t ms) {
 +
 +return 0;
 +
 +<​code>​
 +   ​uint16_t delay_count = 100;
 +   ​volatile uint16_t i;
 +   while (ms != 0) 
 +   {
 +     for (i=0; i != delay_count;​ i++);
 +     ms--;
 +   }
 + ​}</​code>​
 +\t
 +int8_t j, k, m;
 +\t
 +uint8_t position, loopcount, direction, initloopcount,​ already_running,​ softbounce;
 +uint8_t runitout, d_base, a_base, d_mod, a_mod, far_left, far_right;
 +uint8_t ILED, RLED, MLED;\t// Eye position variables: Integer, Modulo, remainder
 +
 +uint8_t delaytime;
 +
 +uint8_t ​ pt, debounce, speedLevel;
 +unsigned int debounce2, BrightMode;
 +\t 
 +uint8_t LED0, LED1, LED2, LED3, LED4, LED5, LED6, LED7, LED8;
 +\t
 +<​nowiki>//</​nowiki>​Initialization routine: Clear watchdog timer-- this can prevent several things from going wrong.\t\t
 +MCUSR &= 0xF7;​\t\t//​Clear WDRF Flag
 +WDTCSR\t= 0x18;​\t\t//​Set stupid bits so we can clear timer...
 +WDTCSR\t= 0x00;
 +
 +<​nowiki>//</​nowiki>​Data direction register: DDR's
 +<​nowiki>//</​nowiki>​Port A: 1 is an output, A0 is an input.\t
 +<​nowiki>//</​nowiki>​Port B: 0-3 are outputs, B4 is an input.\t
 +<​nowiki>//</​nowiki>​Port D: 1-6 are outputs, D0 is an input.
 +\t
 +\tDDRA = 2U;
 +\tDDRB = 15U;\t
 +\tDDRD = 126U;
 +\t
 +\ta_base = 3; // set a base value (resting value) for PA, to keep things easy to modify
 +\td_base = 3; // set a base value (resting value) for PD, to keep things easy to modify
 +\t
 +\tPORTA = a_base;\t// Pull-up resistor enabled, PA0, Port A1 High 
 +\tPORTB = 16;\t// Pull-up resistor enabled, PB4
 +\tPORTD = d_base; ​ // Pull-up resistor enabled, PD0, Port D1 High
 +\t
 +\td_mod = 0;
 +\ta_mod = 0;
 +\t
 +/* Visualize outputs:
 + 
 +<​code>​
 + L to R:
 + D2 D3 D4 D5 D6 B0 B1 B2 B3\t
 + <​-- A1 (out to left)</​code>​
 + 
 +\t  (out to right) D1 -->
 +  ​
 +  * /
 +
 +<​nowiki>//</​nowiki>​ Clear out all of the LED values to blank out the display
 +
 +\tj = 0;
 +\twhile (j < 9) {
 +\t\tLEDs[[j]] = 0; 
 +\t\tj++;
 +\t} 
 +
 +\t LED0 = LEDs[[0]];
 +<​code>​
 +     LED1 = LEDs[[1]];</​code>​
 +\t LED2 = LEDs[[2]];
 +\t LED3 = LEDs[[3]];
 +\t LED4 = LEDs[[4]];
 +\t LED5 = LEDs[[5]];
 +\t LED6 = LEDs[[6]];
 +\t LED7 = LEDs[[7]];
 +\t LED8 = LEDs[[8]]; ​
 +\t
 +<​nowiki>//</​nowiki>​multiplexed = LowPower;\t
 + 
 +\tdebounce = 1; 
 +\tdebounce2 = 1;
 +\tloopcount = 254;
 +\tinitloopcount = 5; 
 +\tdelaytime = 0;
 +\t
 +\tdirection = 0;
 +\tposition = 0;
 +\trunitout = 0;
 +\talready_running = 0;
 +\tsoftbounce = 0;
 +\tfar_left = 0;
 +\tfar_right = 0;
 +\tspeedLevel = 3;  // Range: 1, 2, 3
 +\tBrightMode = 0;
 +
 +if ((PINB & 16) == 0)\t\t// Check if button held on startup; used to verify wiring configuration
 +\t{ initloopcount = 0; // if so, set the startup loop counter to 0 so that we can watch the startup lights
 +\t  softbounce = 1; // Also set the "​soft-bounce"​ mode, which bounces back without leaving the edge, like the original
 +\t}\t
 +
 +delay_ms(200);​
 +
 +PORTD = 1; <​nowiki>//</​nowiki>​Pull D1 low, to trigger output on right side
 +
 +delay_ms(10);​ <​nowiki>//</​nowiki>​Delay to allow output to latch
 +
 +if ((PIND & 1) == 0) <​nowiki>//</​nowiki>​Check to see if D1 output has latched D0 input
 +\tfar_right = 1; //If D0 and D1 are connected, we're at the end of the chain; set far_right so we bounce back from this end
 +
 +PORTD = d_base; <​nowiki>//</​nowiki>​Set D1 high
 +
 +PORTA = 1; <​nowiki>//</​nowiki>​Pull A1 low, to trigger output on left side
 +
 +delay_ms(10);​ <​nowiki>//</​nowiki>​Delay to allow output to latch
 +
 +if ((PINA & 1) == 0) <​nowiki>//</​nowiki>​Check to see if A1 output has latched A0 input
 +\tfar_left = 1; //If A0 and A1 are connected, we're at the end of the chain; set far_left so we bounce back from this end
 +
 +PORTA = a_base; <​nowiki>//</​nowiki>​Set A1 high
 +
 +
 +<​nowiki>//</​nowiki>​A little bit if visual verification to the user as to which way each end of the scanner is set
 +<​nowiki>//</​nowiki>​ (flash outwards if it's open-ended to go to the next scanner in the chain, flash inwards if it's the end and will bounce back
 +
 +if (far_left) {
 +\tleftLED[[0]] = 7;
 +\tleftLED[[1]] = 11;
 +\tleftLED[[2]] = 19;
 +\tleftLED[[3]] = 19;
 +\tleftLED[[4]] = 19;
 +\tleftLED[[5]] = 19;
 +}
 +else {
 +\tleftLED[[0]] = 19;
 +\tleftLED[[1]] = 11;
 +\tleftLED[[2]] = 7;
 +\tleftLED[[3]] = 7;
 +\tleftLED[[4]] = 7;
 +\tleftLED[[5]] = 7;
 +}
 +
 +if (far_right) {
 +\trightLED[[0]] = 24;
 +\trightLED[[1]] = 20;
 +\trightLED[[2]] = 18;
 +\trightLED[[3]] = 18;
 +\trightLED[[4]] = 18;
 +\trightLED[[5]] = 18;
 +}
 +else {
 +\trightLED[[0]] = 18;
 +\trightLED[[1]] = 20;
 +\trightLED[[2]] = 24;
 +\trightLED[[3]] = 24;
 +\trightLED[[4]] = 24;
 +\trightLED[[5]] = 24;
 +}
 +
 +delay_ms(100);​\t/​* Allow all scanners to finish initializing before lighting any LEDs.
 +\t\t\t\t * This is necessary because the clock speeds on each chip only have a 10% tolerance, and initial
 +\t\t\t\t * testing showed that the tests to configure far_left and far_right were causing
 +\t\t\t\t * "​faster"​ chips to get triggered by "​slower"​ chips.
 +\t\t\t\t */
 +for (;;)  <​nowiki>//</​nowiki>​ main loop
 +{
 +\tloopcount++;​
 +
 +\tif (loopcount > delaytime)
 +\t{
 +\t\tloopcount = 0;
 +\t\t
 +\tif ((PINB & 16) == 0) // Check for button press
 +\t{ 
 +\t\tif ((initloopcount >= 4) & (far_left == 1) & (already_running == 0))
 +\t\t{
 +\t\t\trunitout = 1;
 +\t\t\talready_running = 1;
 +\t\t\tdebounce = 0;  // Start running the program, but only on the left-most unit.
 +\t\t}
 +\t\t
 +/*\tThis is the section from the original program to let the button change the speeds and brightness.
 +\t\tdebounce2++;​
 +\t\t
 +\t\tif (debounce2 > 100) 
 +\t\t{   ​debounce2 = 0;
 +\t\t\tdebounce = 0;
 +\t\t\t
 +\t\t if (BrightMode == 0) 
 +\t\t\tBrightMode = 1;
 +\t\t else
 +\t\t\tBrightMode = 0;
 +\t\t\t
 +\t\t}
 +\t\t
 +\t\tif (debounce)
 +\t\t{ 
 +\t\t\tspeedLevel++;​
 +\t\t\t  ​
 +\t\t\tif ((speedLevel == 2) || (speedLevel == 3)) { 
 +\t\t\t\tdelaytime = 0;
 +\t\t\t} ​
 +\t\t\telse ​
 +\t\t\t{ ​  ​speedlevel = 1; 
 +\t\t\t\tdelaytime = 1;
 +\t\t\t}
 +\t\t\t ​
 +\t\tdebounce = 0;
 +\t\t}
 +\t}\t
 +\telse{ ​
 +\tdebounce = 1;
 +\tdebounce2 = 1;
 +\t}
 +  * /\t
 +
 +\t}
 +\t
 +\tif ((PINA & 1) == 0)  // Check to see if display from the left has triggered to start
 +\t{
 +\t\tdirection = 0;
 +\t\trunitout = 1;
 +\t}
 +\t
 +\tif ((PIND & 1) == 0)  // Check to see if display from the right has triggered to start
 +\t{
 +\t\tdirection = 1;
 +\t\trunitout = 1;
 +\t}
 +
 +\t    ​
 +\tif (runitout)
 +\t{
 +\t\tposition++;​
 +\t\t
 +\t\tif (speedLevel == 3)
 +\t\t\tposition++;​
 +\t\t
 +\t\tif ((softbounce == 1) & (((direction == 0) & (far_right == 1)) || ((direction == 1) & (far_left == 1))) & (position >= 224))
 +\t\t{ // this allows us to "​soft-bounce"​ off the ends, like in the original program, without running off the edge
 +\t\t\tposition = 15;
 +\t\t\tif (direction == 0)
 +\t\t\t\tdirection = 1;
 +\t\t\telse
 +\t\t\t\tdirection = 0;
 +\t\t}
 +\t\t
 +\t\tif (position >= 240)\t// To allow for runoff at the ends; was '== 128'
 +\t\t{
 +\t\t\tposition = 0;
 +\t\t 
 +\t\t\tif (direction == 0) {  ​
 +\t\t\t\tdirection = 1;  // we've reached the end, so go back in the other direction
 +\t\t\t\tif (far_right == 0) //  If this isn't the end of the chain, we want to stop, and wait for a signal to go again
 +\t\t\t\t\trunitout = 0;
 +\t\t\t}
 +\t\t\telse {
 +\t\t\t\tdirection = 0;
 +\t\t\t\tif (far_left == 0)  //  If this isn't the end of the chain, we want to stop, and wait for a signal to go again
 +\t\t\t\t\trunitout = 0;
 +\t\t\t}
 +\t\t}
 +\t\t \t\t
 +\tif (direction == 0)  // Moving to right, as viewed from front.
 +\t{   
 +\t\tILED = (15+position) >> 4; 
 +\t\tRLED = (15+position) - (ILED << 4);
 +\t\tMLED = 15 - RLED; \t\t
 +\t}
 +<​code>​
 +    else </​code>​
 +\t{   
 +\t\tILED = (127 - position) >> 4;  ​
 +\t\tMLED = (127 - position) ​ - (ILED << 4);
 +\t\tRLED =  15 - MLED;\t
 +\t}
 +\t
 +\tif ((ILED == 10) & (direction == 0) & (far_right == 0))
 +\t\td_mod = 2; // If we're heading to the right, and we're not at the end of the chain, we want to trigger D1 to start the next scanner
 +\t\t
 +\tj = 0;
 +\twhile (j < 9) {
 +\t\tLEDs[[j]] = 0; 
 +\t\tj++;
 +\t}  ​
 +\t\t 
 +\tj = 0;
 +\tif ((softbounce == 1) & (((direction == 0) & (far_right == 1)) || ((direction == 1) & (far_left == 1)))) { 
 +\t\twhile (j < 5) {
 +\t\t\t
 +\t\t\tif (direction == 0) 
 +\t\t\t ​  m = ILED - (j + 1);
 +\t\t\t ​  //m = ILED + (2 - j);\t// e.g., eyeLoc[[0]] = ILED + 2; 
 +\t\t\telse
 +\t\t\t ​  m = ILED + (j + 1);
 +\t\t\t ​  //m = ILED + (j - 2);  // e.g., eyeLoc[[0]] = ILED - 2;
 +\t\t\t
 +\t\t\tif ((direction == 0) & (m > 8))
 +\t\t\t\tm = 8;
 +\t\t\t
 +\t\t\tif ((direction == 1) & (m < 0))
 +\t\t\t\tm = 0;
 +\t\t\t
 +\t\t\teyeLoc[[j]] = m;
 +\t\t\t
 +\t\t\tj++;
 +\t\t}
 +\t}
 +\telse {
 +\t\twhile (j < 5)
 +\t\t{\t\t
 +\t\t\tif (direction == 0) 
 +\t\t\t\tm = ILED - (j + 1);\t// e.g., eyeLoc[[0]] = ILED - 1; 
 +\t\t\telse
 +\t\t\t\tm = ILED + (j + 1); // e.g., eyeLoc[[0]] = ILED + 1;
 +\t\t\t
 +\t\t\tif ((m == -1) & (direction == 1) & (far_left == 0))
 +\t\t\t\ta_mod = 2; // If we're heading to the left, and we're not at the end of the chain, we want to trigger A1 to start the next scanner
 +\t\t
 +\t\t\tif (m > 8)
 +\t\t\t\tm = -1;  // If eye position is past the end of the board, don't light it; set to -1
 +\t\t\t\t\t\t
 +\t\t\tif (m < 0)
 +\t\t\t\tm = -1;  // If eye position is past the end of the board, don't light it; set to -1
 +\t\t\t
 +\t\t\teyeLoc[[j]] = m;
 +\t\t\t
 +\t\t\tj++;
 +\t\t} 
 +\t}
 +\t\t  ​
 +\tj = 0;\t\t// For each of the eye parts...
 +\twhile (j < 4) 
 +\t{\t\t
 +\t\tif (eyeLoc[[j]] >= 0)
 +\t\t\tLEDs[eyeLoc[j]] ​  += LEDBright[[j]]*RLED;​\t
 +\t\tif (eyeLoc[[j+1]] >= 0)
 +\t\t\tLEDs[eyeLoc[j+1]] += LEDBright[[j]]*MLED;​
 +\t\tj++;
 +\t}  ​
 +\t
 +\t LED0 = LEDs[[0]];
 +<​code>​
 +     LED1 = LEDs[[1]];</​code>​
 +\t LED2 = LEDs[[2]];
 +\t LED3 = LEDs[[3]];
 +\t LED4 = LEDs[[4]];
 +\t LED5 = LEDs[[5]];
 +\t LED6 = LEDs[[6]];
 +\t LED7 = LEDs[[7]];
 +\t LED8 = LEDs[[8]];  ​
 +\t}
 +\telse if (initloopcount < 4 )
 +\t{
 +\t\tk = 0;
 +\t\twhile (k < 6) {
 +\t\t\tPORTD = leftLED[[k]];​
 +\t\t\tPORTB = rightLED[[k]];​
 +\t\t\tdelay_ms(1);​
 +\t\t
 +\t\t\tPORTD = d_base;
 +\t\t\tPORTB = 16;
 +\t\t\tdelay_ms(29);​
 +
 +\t\t\tk++;
 +\t\t}
 +\t\tdelay_ms(100);​
 +\t\tinitloopcount++;​
 +\t}
 +\t}
 +\tif (runitout) {
 +\tif (BrightMode == 0)
 +\t{\t\t//​multiplexing routine: each led is on (1/9) of the time. 
 +\t\t\t// ​ -> Use much less power.
 +\t\tj = 0;
 +\t\tPORTA = a_base - a_mod; // we set a_mod to correspond to A1's bit in PORTA; this makes it easier to change the pin configs later
 +\t\twhile (j < 60)\t\t// Truncate brightness at a max value (60) in the interest of speed.
 +\t\t{
 +\t\t  ​
 +\tif (LED0 > j) 
 +\t\tPORTD = 7 - d_mod; ​ // we set d_mod to correspond to D1's bit in PORTD; this makes it easier to change the trigger pin configs later
 +\telse\t
 +\t\tPORTD = d_base - d_mod;  ​
 +\t\t\t
 +\tif (LED1 > j) 
 +\t\tPORTD = 11 - d_mod;\t
 +\telse\t
 +\t\tPORTD = d_base - d_mod;​\t ​
 +\t\t\t
 +\tif (LED2 > j) 
 +\t\tPORTD = 19 - d_mod; ​
 +\telse\t
 +\t\tPORTD = d_base - d_mod; ​
 +\t\t\t
 +\tif (LED3 > j) 
 +\t\tPORTD = 35 - d_mod;\t
 +\telse\t
 +\t\tPORTD = d_base - d_mod;
 +\t\t\t
 +\tif (LED4 > j) 
 +\t\tPORTD = 67 - d_mod;
 +\telse\t
 +\t\tPORTD = d_base - d_mod;
 +\t\t  ​
 +\tif (LED5 > j) {
 +\t\tPORTB = 17;\t 
 +\t\tPORTD = d_base - d_mod;}
 +\telse\t{
 +\t\tPORTB = 16;
 +\t\tPORTD = d_base - d_mod;}
 +\t\t\t
 +\tif (LED6 > j) 
 +\t\tPORTB = 18;\t
 +\telse\t
 +\t\tPORTB = 16;
 +\t\t\t
 +\tif (LED7 > j) 
 +\t\tPORTB = 20;\t
 +\telse\t
 +\t\tPORTB = 16;
 +\t\t\t
 +\tif (LED8 > j) 
 +\t\tPORTB = 24;\t
 +\telse\t
 +\t\tPORTB = 16; 
 +\t\t 
 +\t\tj++;
 +<​nowiki>//</​nowiki>​\t\tif (speedLevel == 3)
 +<​nowiki>//</​nowiki>​\t\t\tj++;​
 +\t\t PORTB = 16; 
 +\t} 
 +\t 
 +\td_mod = 0;
 +\ta_mod = 0;
 +\t} 
 +\t else 
 +\t {\t\t// full power routine
 +\t 
 +\t  PORTA = a_base - a_mod;
 +
 +\t  j = 0;
 +\t  while (j < 70)
 +\t  {
 +\t  ​
 +\t  ​
 +\t  pt = d_base - d_mod;\t
 +\t  if (LED0 > j) 
 +\t  pt |= 4; 
 +\t  if (LED1 > j) 
 +\t  pt |= 8;\t
 +\t  if (LED2 > j) 
 +\t  pt |= 16; 
 +\t  if (LED3 > j) 
 +\t  pt |= 32;​\t\t ​
 +\t  if (LED4 > j) 
 +\t  pt |= 64;
 +\t  ​
 +\t  PORTD = pt;
 +\t  shortdelay(); ​
 +\t  pt = 16;\t
 +\t  if (LED5 > j) 
 +\t  pt |= 1;\t
 +\t  if (LED6 > j) 
 +\t  pt |= 2;\t
 +\t  if (LED7 > j) 
 +\t  pt |= 4;\t
 +\t  if (LED8 > j) 
 +\t  pt |= 8;\t\t\t
 +\t  ​
 +\t  PORTB = pt;
 +\t  shortdelay(); ​
 +\t\t  ​
 +\t  j++;
 +<​nowiki>//</​nowiki>​\t ​ if (speedLevel == 3)
 +<​nowiki>//</​nowiki>​\t ​ j++;
 +\t  }
 +\t
 +\t d_mod = 0; // we want to stop triggering D1, so set the modifier of PORTD back to 0
 +\t a_mod = 0; // we want to stop triggering A1, so set the modifier of PORTA back to 0
 +\t 
 +\t }
 +\t}
 +\t 
 +<​nowiki>//</​nowiki>​Multiplexing routine: Each LED is on (1/9) of the time. 
 +<​nowiki>//</​nowiki> ​ -> Uses much less power.
 +<​code>​
 +   PORTA = a_base - a_mod;</​code>​
 +\t}\t//End main loop
 +\treturn 0;
 +}
 +
 +  - endif
 +\t
 +</​code>​
  
nsl_cylon.txt ยท Last modified: 2013/08/13 12:13 (external edit)