├── .gitattributes ├── .gitignore ├── AS7 ├── README.md ├── blink │ ├── BareMinimumTemplate.zip │ ├── Sketches │ │ ├── BareMinimum │ │ │ ├── BareMinimum.componentinfo.xml │ │ │ ├── BareMinimum.cppproj │ │ │ └── main.cpp │ │ └── Blink │ │ │ ├── Blink.componentinfo.xml │ │ │ ├── Blink.cppproj │ │ │ └── main.cpp │ ├── Snipets │ │ └── special_serial.xml │ ├── bareblinkOS │ │ └── bareblinkOS │ │ │ ├── bareblinkOS.componentinfo.xml │ │ │ ├── bareblinkOS.cppproj │ │ │ ├── blinkos.h │ │ │ ├── main.cpp │ │ │ └── pixelcolor.h │ ├── blink.atsln │ ├── blinkcore │ │ ├── blinkcore.componentinfo.xml │ │ └── blinkcore.cppproj │ ├── blinklib │ │ ├── WMath.cpp │ │ ├── blinkos.componentinfo.xml │ │ └── blinkos.cppproj │ └── blinkstate │ │ ├── blinklib.componentinfo.xml │ │ └── blinklib.cppproj ├── blinklib │ └── blinklib │ │ ├── blinklib.componentinfo.xml │ │ └── blinklib.cppproj └── blinkos │ └── blinkos │ ├── blinkos.componentinfo.xml │ └── blinkos.cppproj ├── Getting-started.md ├── LICENSE ├── Layers.md ├── Production.MD ├── README.md ├── Service Port.MD ├── Tools.md ├── _config.yml ├── avrdude.conf ├── boards.txt ├── bootloaders ├── BlinkBIOS.hex └── readme.MD ├── cores └── blinklib │ ├── Arduino.h │ ├── ArduinoTypes.h │ ├── DummySerial.h │ ├── Print.cpp │ ├── Print.h │ ├── Serial.cpp │ ├── Serial.h │ ├── Timer.cpp │ ├── blinklib.cpp │ ├── blinklib.h │ ├── main.cpp │ ├── run.h │ ├── shared │ ├── BlinkBIOS.hex │ ├── blinkbios_shared_button.h │ ├── blinkbios_shared_functions.h │ ├── blinkbios_shared_irdata.h │ ├── blinkbios_shared_millis.h │ ├── blinkbios_shared_pixel.h │ ├── blinkbios_shared_volatile.h │ └── readme.MD │ ├── sp.cpp │ ├── sp.h │ └── startup.S ├── keywords.txt ├── libraries ├── Examples01 │ ├── dummy.hpp │ ├── examples │ │ ├── A-BareMinimum │ │ │ └── A-BareMinimum.ino │ │ ├── B-ButtonPress │ │ │ └── B-ButtonPress.ino │ │ ├── C-ButtonCycleColors │ │ │ └── C-ButtonCycleColors.ino │ │ ├── D-TimerFlash │ │ │ └── D-TimerFlash.ino │ │ ├── E-TimerBlink │ │ │ └── E-TimerBlink.ino │ │ ├── F-ColorWheel │ │ │ └── F-ColorWheel.ino │ │ └── G-StartState │ │ │ └── G-StartState.ino │ └── library.properties ├── Examples02 │ ├── dummy.hpp │ ├── examples │ │ ├── A-ColorByNeighbor │ │ │ └── A-ColorByNeighbor.ino │ │ ├── B-ColorRamps │ │ │ └── B-ColorRamps.ino │ │ ├── C-SerialNumberPrinter │ │ │ └── C-SerialNumberPrinter.ino │ │ ├── D-SerialTest │ │ │ └── D-SerialTest.ino │ │ ├── E-ButtonGym │ │ │ └── E-ButtonGym.ino │ │ ├── F-SimpleDatagramDemo │ │ │ └── F-SimpleDatagramDemo.ino │ │ ├── G-IRButtonPressTester │ │ │ └── G-IRButtonPressTester.ino │ │ └── H-IRLinkTester │ │ │ └── H-IRLinkTester.ino │ └── library.properties ├── Examples03 │ ├── dummy.hpp │ ├── examples │ │ ├── Astro │ │ │ └── Astro.ino │ │ ├── Berry │ │ │ └── Berry.ino │ │ ├── BombBrigade │ │ │ └── BombBrigade.ino │ │ ├── FlicFlop │ │ │ └── FlicFlop.ino │ │ ├── Fracture │ │ │ └── Fracture.ino │ │ ├── Honey │ │ │ └── Honey.ino │ │ ├── Mortals │ │ │ └── Mortals.ino │ │ ├── Puzzle101 │ │ │ └── Puzzle101.ino │ │ ├── SpeedRacer │ │ │ └── SpeedRacer.ino │ │ ├── WHAM │ │ │ └── WHAM.ino │ │ ├── Widgets │ │ │ └── Widgets.ino │ │ └── ZenFlow │ │ │ └── ZenFlow.ino │ └── library.properties ├── Examples04 │ ├── dummy.hpp │ └── library.properties └── Examples05 │ ├── dummy.hpp │ └── library.properties ├── linkscripts ├── avr5.xn └── readme.MD ├── package_move38.com-blinks_index.json ├── platform.txt ├── programmers.txt └── variants └── standard └── dummy.txt /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | [Dd]ebug/ 3 | [Rr]elease/ 4 | .vs* 5 | -------------------------------------------------------------------------------- /AS7/README.md: -------------------------------------------------------------------------------- 1 | # AS7 2 | 3 | This directory holds an Atmel Studio 7 Solution and Project with all the firmware files. 4 | 5 | All files are included as links to the arduino directories, so any updates you make in AS7 will be reflected in the arduino structure. 6 | 7 | There is a project temple here called `` that makes it easy to create new sketches that use the `blinkslib` library. You need to import this zip file into Atmel Studio... 8 | 9 | http://www.atmel.com/webdoc/atmelstudio/atmelstudio.GettingStarted.ProjectImporter.TemplateImporter.html 10 | 11 | ...and then you can use "Add New Project..." to quickly make new sketches with all the setting and directories right. 12 | 13 | After you are done, you can copy and paste the source code into a INO file in the Arduino IDE. 14 | 15 | I much prefer working in AS7 to the Arduino IDE so it was worth the effort to make this. 16 | -------------------------------------------------------------------------------- /AS7/blink/BareMinimumTemplate.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Move38/Blinks-SDK/2fd2e45e02ffd8c4ac6468d7cb420dcd29306c9f/AS7/blink/BareMinimumTemplate.zip -------------------------------------------------------------------------------- /AS7/blink/Sketches/BareMinimum/BareMinimum.componentinfo.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | Device 8 | Startup 9 | 10 | 11 | Atmel 12 | 1.2.0 13 | C:/Program Files (x86)\Atmel\Studio\7.0\Packs 14 | 15 | 16 | 17 | 18 | C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.2.132\include 19 | 20 | include 21 | C 22 | 23 | 24 | include 25 | 26 | 27 | 28 | 29 | C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.2.132\include\avr\iom168pb.h 30 | 31 | header 32 | C 33 | L5o1bjrhZ5Pw/8Zpd6GGNw== 34 | 35 | include/avr/iom168pb.h 36 | 37 | 38 | 39 | 40 | C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.2.132\templates\main.c 41 | template 42 | source 43 | C Exe 44 | GD1k8YYhulqRs6FD1B2Hog== 45 | 46 | templates/main.c 47 | Main file (.c) 48 | 49 | 50 | 51 | C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.2.132\templates\main.cpp 52 | template 53 | source 54 | C Exe 55 | OiG8MbOIHSxLATGuTbJvtg== 56 | 57 | templates/main.cpp 58 | Main file (.cpp) 59 | 60 | 61 | 62 | C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.2.132\gcc\dev\atmega168pb 63 | 64 | libraryPrefix 65 | GCC 66 | 67 | 68 | gcc/dev/atmega168pb 69 | 70 | 71 | 72 | 73 | ATmega_DFP 74 | C:/Program Files (x86)/Atmel/Studio/7.0/Packs/atmel/ATmega_DFP/1.2.132/Atmel.ATmega_DFP.pdsc 75 | 1.2.132 76 | true 77 | ATmega168PB 78 | 79 | 80 | 81 | Resolved 82 | Fixed 83 | true 84 | 85 | 86 | -------------------------------------------------------------------------------- /AS7/blink/Sketches/BareMinimum/BareMinimum.cppproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 2.0 5 | 7.0 6 | com.Atmel.AVRGCC8.CPP 7 | {89039130-47b6-4762-beb5-52050924dfe0} 8 | ATmega168PB 9 | none 10 | Executable 11 | CPP 12 | $(MSBuildProjectName) 13 | .elf 14 | $(MSBuildProjectDirectory)\$(Configuration) 15 | BareMinimum 16 | BareMinimum 17 | BareMinimum 18 | Native 19 | true 20 | false 21 | true 22 | true 23 | 24 | 25 | true 26 | 27 | 2 28 | 0 29 | 30 | 31 | 32 | 33 | -mmcu=atmega168pb -B "%24(PackRepoDir)\atmel\ATmega_DFP\1.2.132\gcc\dev\atmega168pb" 34 | True 35 | True 36 | True 37 | True 38 | False 39 | True 40 | True 41 | 42 | 43 | NDEBUG 44 | 45 | 46 | 47 | 48 | %24(PackRepoDir)\atmel\ATmega_DFP\1.2.132\include 49 | 50 | 51 | Optimize for size (-Os) 52 | True 53 | True 54 | True 55 | True 56 | True 57 | 58 | 59 | NDEBUG 60 | 61 | 62 | 63 | 64 | %24(PackRepoDir)\atmel\ATmega_DFP\1.2.132\include 65 | 66 | 67 | Optimize for size (-Os) 68 | True 69 | True 70 | True 71 | 72 | 73 | libm 74 | 75 | 76 | 77 | 78 | %24(PackRepoDir)\atmel\ATmega_DFP\1.2.132\include 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | -mmcu=atmega168pb -B "%24(PackRepoDir)\atmel\ATmega_DFP\1.2.132\gcc\dev\atmega168pb" 88 | True 89 | True 90 | True 91 | True 92 | False 93 | True 94 | True 95 | 96 | 97 | DEBUG 98 | 99 | 100 | 101 | 102 | %24(PackRepoDir)\atmel\ATmega_DFP\1.2.132\include 103 | 104 | 105 | Optimize (-O1) 106 | True 107 | True 108 | Default (-g2) 109 | True 110 | True 111 | True 112 | 113 | 114 | DEBUG 115 | 116 | 117 | 118 | 119 | %24(PackRepoDir)\atmel\ATmega_DFP\1.2.132\include 120 | ../../../../../libraries/blinklib/src 121 | ../../../../../cores/blinkcore 122 | 123 | 124 | Optimize (-O1) 125 | True 126 | True 127 | Default (-g2) 128 | True 129 | 130 | 131 | libm 132 | 133 | 134 | 135 | 136 | %24(PackRepoDir)\atmel\ATmega_DFP\1.2.132\include 137 | 138 | 139 | Default (-Wa,-g) 140 | 141 | 142 | 143 | 144 | 145 | compile 146 | 147 | 148 | 149 | 150 | blinkcore 151 | {dce6c7e3-ee26-4d79-826b-08594b9ad897} 152 | True 153 | 154 | 155 | blinklib 156 | {c03aa8ca-16e3-4a37-9986-eeaa5cbcefd6} 157 | True 158 | 159 | 160 | 161 | -------------------------------------------------------------------------------- /AS7/blink/Sketches/BareMinimum/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * BareMinimum.cpp 3 | * 4 | */ 5 | 6 | #include 7 | 8 | #include "blink.h" 9 | 10 | void setup() { 11 | // put your start up code here, it will run 12 | // every time this blink wakes up 13 | 14 | } 15 | 16 | void loop() { 17 | // put your main code here, to run repeatedly 18 | // every time a new frame of pixels is displayed 19 | // on the front of this blink 20 | 21 | } 22 | -------------------------------------------------------------------------------- /AS7/blink/Sketches/Blink/Blink.componentinfo.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | Device 8 | Startup 9 | 10 | 11 | Atmel 12 | 1.2.0 13 | C:/Program Files (x86)\Atmel\Studio\7.0\Packs 14 | 15 | 16 | 17 | 18 | C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.2.209\include 19 | 20 | include 21 | C 22 | 23 | 24 | include 25 | 26 | 27 | 28 | 29 | C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.2.209\include\avr\iom168pb.h 30 | 31 | header 32 | C 33 | yAkfp/rOk1YuAUNFypsCqg== 34 | 35 | include/avr/iom168pb.h 36 | 37 | 38 | 39 | 40 | C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.2.209\templates\main.c 41 | template 42 | source 43 | C Exe 44 | GD1k8YYhulqRs6FD1B2Hog== 45 | 46 | templates/main.c 47 | Main file (.c) 48 | 49 | 50 | 51 | C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.2.209\templates\main.cpp 52 | template 53 | source 54 | C Exe 55 | YXFphlh0CtZJU+ebktABgQ== 56 | 57 | templates/main.cpp 58 | Main file (.cpp) 59 | 60 | 61 | 62 | C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.2.209\gcc\dev\atmega168pb 63 | 64 | libraryPrefix 65 | GCC 66 | 67 | 68 | gcc/dev/atmega168pb 69 | 70 | 71 | 72 | 73 | ATmega_DFP 74 | C:/Program Files (x86)/Atmel/Studio/7.0/Packs/atmel/ATmega_DFP/1.2.209/Atmel.ATmega_DFP.pdsc 75 | 1.2.209 76 | true 77 | ATmega168PB 78 | 79 | 80 | 81 | Resolved 82 | Fixed 83 | true 84 | 85 | 86 | -------------------------------------------------------------------------------- /AS7/blink/Sketches/Blink/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define F_CPU 8000000 4 | 5 | #include 6 | 7 | //#include "bitfun.h" 8 | 9 | //#include "adc.h" 10 | 11 | #include "Serial.h" 12 | 13 | ServicePortSerial sp; 14 | 15 | 16 | void setup() { 17 | 18 | sp.begin(); 19 | 20 | } 21 | 22 | 23 | // Returns the previous conversion result (call adc_startConversion() to start a conversion). 24 | // Blocks if you call too soon and conversion not ready yet. 25 | 26 | uint8_t adc_readLastVccX10(void) { // Return Vcc x10 27 | 28 | while (TBI(ADCSRA,ADSC)) ; // Wait for any pending conversion to complete 29 | 30 | uint8_t lastReading = (255*11 / ADCH); // Remember the result from the last reading. 31 | 32 | sp.println(lastReading); 33 | 34 | return( lastReading ); 35 | 36 | } 37 | 38 | #define DELAY_BLINK_MS 200 // Delay between flashes 39 | #define DELAY_DIGIT_MS 750 // Delay between 10's and 1's digits 40 | #define DELAY_READ_MS 1000 // Delay between consecutive readings 41 | 42 | 43 | 44 | enum phase_t { READ , TENS, ONES }; 45 | 46 | enum state_t { S_OFF , S_ON }; 47 | 48 | static phase_t phase=READ; 49 | static state_t state=S_OFF; 50 | 51 | static Timer next; 52 | 53 | static uint8_t c=0; 54 | 55 | static uint8_t lastReading=24; 56 | 57 | void loop() { 58 | /* 59 | if (next.isExpired()) { 60 | 61 | if (state==S_ON) { 62 | 63 | setColor( OFF ); 64 | 65 | state=S_OFF; 66 | 67 | } else { 68 | setColor( BLUE ); 69 | 70 | state=S_ON; 71 | 72 | } 73 | 74 | next.set(500); 75 | 76 | } 77 | 78 | return; 79 | */ 80 | 81 | if (phase==READ) { 82 | 83 | adc_startConversion(); 84 | 85 | lastReading = adc_readLastVccX10(); 86 | 87 | c = lastReading/10; // Tens digit 88 | 89 | if (c==0) c=10; 90 | 91 | phase = TENS; 92 | 93 | state = S_OFF; 94 | 95 | next.set(2000); // Show immediately 96 | 97 | } 98 | 99 | if (c==0) { // Done with this digit 100 | 101 | if (phase==TENS) { 102 | 103 | c = lastReading%10; // Ones digit 104 | 105 | if (c==0) c=10; 106 | 107 | phase = ONES; 108 | 109 | next.set( DELAY_DIGIT_MS ); 110 | 111 | } else { 112 | 113 | phase = READ; 114 | 115 | next.set( DELAY_READ_MS ); 116 | } 117 | 118 | } else { 119 | 120 | if (next.isExpired()) { 121 | 122 | if (state==S_OFF) { 123 | 124 | setColor( RED ); 125 | 126 | state = S_ON; 127 | 128 | next.set( DELAY_BLINK_MS ); 129 | 130 | } else { // state==ON 131 | 132 | setColor( OFF ); 133 | 134 | state = S_OFF; 135 | 136 | c--; 137 | 138 | next.set( DELAY_BLINK_MS ); 139 | 140 | } 141 | 142 | } 143 | 144 | } 145 | 146 | } // loop() 147 | 148 | 149 | -------------------------------------------------------------------------------- /AS7/blink/Snipets/special_serial.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 |
6 | Special serial debuging snippet 7 |
8 | 9 | 10 | 18 | #define SP_SERIAL_CTRL_REG UCSR0A 19 | #define SP_SERIAL_DATA_REG UDR0 20 | #define SP_SERIAL_READY_BIT RXC0 21 | 22 | static void sp_serial_tx(uint8_t b) { 23 | 24 | while (!TBI(SP_SERIAL_CTRL_REG,UDRE0)); // Wait for buffer to be clear so we don't overwrite in progress 25 | 26 | SP_SERIAL_DATA_REG=b; // Send new byte 27 | 28 | } 29 | 30 | /* TO HERE */ 31 | 32 | 33 | 34 | ]]> 35 | 36 | 37 |
38 |
39 | 40 | 41 | -------------------------------------------------------------------------------- /AS7/blink/bareblinkOS/bareblinkOS/bareblinkOS.componentinfo.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | Device 8 | Startup 9 | 10 | 11 | Atmel 12 | 1.2.0 13 | C:/Program Files (x86)\Atmel\Studio\7.0\Packs 14 | 15 | 16 | 17 | 18 | C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.2.209\include 19 | 20 | include 21 | C 22 | 23 | 24 | include 25 | 26 | 27 | 28 | 29 | C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.2.209\include\avr\iom168pb.h 30 | 31 | header 32 | C 33 | yAkfp/rOk1YuAUNFypsCqg== 34 | 35 | include/avr/iom168pb.h 36 | 37 | 38 | 39 | 40 | C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.2.209\templates\main.c 41 | template 42 | source 43 | C Exe 44 | GD1k8YYhulqRs6FD1B2Hog== 45 | 46 | templates/main.c 47 | Main file (.c) 48 | 49 | 50 | 51 | C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.2.209\templates\main.cpp 52 | template 53 | source 54 | C Exe 55 | CAoCZxJJ1rIlxmxWa+AEaw== 56 | 57 | templates/main.cpp 58 | Main file (.cpp) 59 | 60 | 61 | 62 | C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.2.209\gcc\dev\atmega168pb 63 | 64 | libraryPrefix 65 | GCC 66 | 67 | 68 | gcc/dev/atmega168pb 69 | 70 | 71 | 72 | 73 | ATmega_DFP 74 | C:/Program Files (x86)/Atmel/Studio/7.0/Packs/atmel/ATmega_DFP/1.2.209/Atmel.ATmega_DFP.pdsc 75 | 1.2.209 76 | true 77 | ATmega168PB 78 | 79 | 80 | 81 | Resolved 82 | Fixed 83 | true 84 | 85 | 86 | -------------------------------------------------------------------------------- /AS7/blink/bareblinkOS/bareblinkOS/bareblinkOS.cppproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 2.0 5 | 7.0 6 | com.Atmel.AVRGCC8.CPP 7 | {b750fa7b-22de-43c4-a796-f95418271edd} 8 | ATmega168PB 9 | none 10 | Executable 11 | CPP 12 | $(MSBuildProjectName) 13 | .elf 14 | $(MSBuildProjectDirectory)\$(Configuration) 15 | bareblinkOS 16 | bareblinkOS 17 | bareblinkOS 18 | Native 19 | true 20 | false 21 | true 22 | true 23 | 0x20000000 24 | 25 | true 26 | exception_table 27 | 2 28 | 0 29 | 0 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | com.atmel.avrdbg.tool.ispmk2 44 | 0000B3020609 45 | 0x1E9415 46 | ISP 47 | 250000 48 | 49 | 50 | 51 | 250000 52 | 53 | ISP 54 | 55 | com.atmel.avrdbg.tool.ispmk2 56 | 0000B3020609 57 | AVRISP mkII 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | -mmcu=atmega168pb -B "%24(PackRepoDir)\atmel\ATmega_DFP\1.2.209\gcc\dev\atmega168pb" 68 | True 69 | True 70 | True 71 | True 72 | False 73 | True 74 | True 75 | 76 | 77 | NDEBUG 78 | 79 | 80 | 81 | 82 | %24(PackRepoDir)\atmel\ATmega_DFP\1.2.209\include 83 | 84 | 85 | Optimize for size (-Os) 86 | True 87 | True 88 | True 89 | True 90 | True 91 | 92 | 93 | NDEBUG 94 | 95 | 96 | 97 | 98 | %24(PackRepoDir)\atmel\ATmega_DFP\1.2.209\include 99 | 100 | 101 | Optimize for size (-Os) 102 | True 103 | True 104 | True 105 | 106 | 107 | libm 108 | 109 | 110 | 111 | 112 | %24(PackRepoDir)\atmel\ATmega_DFP\1.2.209\include 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | -mmcu=atmega168pb -B "%24(PackRepoDir)\atmel\ATmega_DFP\1.2.209\gcc\dev\atmega168pb" 122 | True 123 | True 124 | True 125 | True 126 | False 127 | True 128 | True 129 | 130 | 131 | DEBUG 132 | 133 | 134 | 135 | 136 | %24(PackRepoDir)\atmel\ATmega_DFP\1.2.209\include 137 | 138 | 139 | Optimize (-O1) 140 | True 141 | True 142 | Default (-g2) 143 | True 144 | True 145 | True 146 | 147 | 148 | DEBUG 149 | 150 | 151 | 152 | 153 | %24(PackRepoDir)\atmel\ATmega_DFP\1.2.209\include 154 | 155 | 156 | Optimize (-O1) 157 | True 158 | True 159 | Default (-g2) 160 | True 161 | 162 | 163 | libm 164 | 165 | 166 | 167 | 168 | %24(PackRepoDir)\atmel\ATmega_DFP\1.2.209\include 169 | 170 | 171 | Default (-Wa,-g) 172 | 173 | 174 | 175 | 176 | 177 | compile 178 | 179 | 180 | 181 | -------------------------------------------------------------------------------- /AS7/blink/bareblinkOS/bareblinkOS/blinkos.h: -------------------------------------------------------------------------------- 1 | /* 2 | * blinkOS.h 3 | * 4 | * This defines a high-level interface to the blinks operating system. 5 | * 6 | */ 7 | 8 | 9 | // Gets us uintx_t 10 | // Not sure why, but it MUST be in the header and not the cpp 11 | #include 12 | #include "pixelcolor.h" 13 | 14 | #define IR_FACE_COUNT 6 15 | #define IR_FACE_BITMASK 0b00111111 // 1's in each bit for every face (will break if we ever make a nonagon or higher) 16 | 17 | #define PIXEL_FACE_COUNT 6 18 | 19 | // TODO: Change time to uint24 _t 20 | // Supported!!! https://gcc.gnu.org/wiki/avr-gcc#types 21 | // typedef __uint24 millis_t; 22 | 23 | typedef uint32_t millis_t; 24 | 25 | // loopstate is passed in and out of the user program on each pass 26 | // through the main event loop 27 | 28 | // I know this is ugly, but keeping them in a single byte lets us pass them by value 29 | // and also lets us OR them together. Efficiency in the updater trumps since it 30 | // runs every millisecond. 31 | 32 | #define BUTTON_BITFLAG_PRESSED 0b00000001 33 | #define BUTTON_BITFLAG_LONGPRESSED 0b00000010 34 | #define BUTTON_BITFLAG_RELEASED 0b00000100 35 | #define BUTTON_BITFLAG_SINGLECLICKED 0b00001000 36 | #define BUTTON_BITFLAG_DOUBLECLICKED 0b00010000 37 | #define BUTTON_BITFLAG_MULITCLICKED 0b00100000 38 | #define BUTTON_BITFLAG_DUMMY 0b01000000 39 | 40 | struct buttonstate_t { 41 | 42 | uint8_t down; // 1 if button is currently down 43 | 44 | uint8_t bitflags; 45 | 46 | uint8_t clickcount; // Number of clicks on most recent multiclick 47 | 48 | }; 49 | 50 | 51 | struct ir_data_buffer_t { 52 | 53 | const uint8_t *data; 54 | uint8_t len; 55 | uint8_t ready_flag; // 1 if new packet received. Call markread_data_buffer(); 56 | 57 | }; 58 | 59 | // Sends immediately. Blocks until send is complete. 60 | // Higher level should provide some collision control. 61 | // Returns 0 if it was not able to send because there was already an RX in progress on this face 62 | 63 | uint8_t ir_send_userdata( uint8_t face, const uint8_t *data , uint8_t len ); 64 | 65 | struct loopstate_in_t { 66 | 67 | ir_data_buffer_t ir_data_buffers[IR_FACE_COUNT]; 68 | 69 | buttonstate_t buttonstate; // Note that the flags in here are cleared after every pass though the loop 70 | 71 | uint8_t woke_flag; // Have we slept and woke? 72 | 73 | 74 | millis_t millis; // elapsed milliseconds since start 75 | 76 | uint8_t futureexapansion[20]; // Save some space for future expansion 77 | 78 | }; 79 | 80 | // Mark a packet as consumed so the buffer can receive the next one. 81 | // Done automatically each time loopEntry() returns, but this can let you free up the packet sooner 82 | // for better throughput 83 | 84 | // Mark a packet as consumed so the buffer can receive the next one. 85 | // Done automatically each time loopEntry() returns, but this can let you free up the packet sooner 86 | // for better throughput 87 | 88 | void ir_mark_packet_read( uint8_t face ); 89 | 90 | struct loopstate_out_t { 91 | 92 | pixelColor_t colors[PIXEL_FACE_COUNT]; // Current RGB colors of all faces. 5 bits each. 93 | // Topmost bit set indicates it changed 94 | 95 | uint8_t futureexapansion[20]; // Save some space for future expansion 96 | 97 | }; 98 | 99 | 100 | // These are provided by blinklib 101 | 102 | //void setupEntry(); 103 | void loopEntry( loopstate_in_t const *loopstate_in , loopstate_out_t *loopstate_out); 104 | -------------------------------------------------------------------------------- /AS7/blink/bareblinkOS/bareblinkOS/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * bareblinkOS.cpp 3 | * 4 | * An example that runs directly on the blinkOS without blinklib 5 | * 6 | */ 7 | 8 | 9 | #include "blinkos.h" 10 | //#include "bootloader.h" 11 | 12 | //#include // memcmp() 13 | 14 | 15 | void setupEntry() { 16 | 17 | // Blank 18 | 19 | }; 20 | 21 | Timer next_send_pull_request; 22 | 23 | void loopEntry() { 24 | 25 | if (next_send_pull_request.isExpired()) { 26 | 27 | // Time to send next pull request 28 | 29 | blinkboot_packet p; 30 | 31 | p.header = P 32 | 33 | } 34 | 35 | } 36 | 37 | 38 | 39 | /* 40 | //uint8_t *cookie = (uint8_t *) "Josh is a *very* nice, good guy."; // 32 bytes long (includes trailing null) 41 | //#define COOKIE_SIZE 32 42 | 43 | uint8_t cookie[] = {0b10110111}; // Non repeating bit pattern to detect errors. 44 | #define COOKIE_SIZE 1 45 | 46 | #define TX_PROBE_TIME_MS 250 // How often to do a blind send when no RX has happened recently to trigger ping pong 47 | 48 | #define MISSED_RX_SHOW_TIME_MS 500 // How long to show blue when a RX timeout happens 49 | #define RX_TIMEOUT_RX 200 // If we do not see a message in this long, then show a timeout 50 | 51 | // Note these all init to 0's, which is what we want. 52 | 53 | struct face_t { 54 | 55 | millis_t next_tx_ms; // Next time to transmit 56 | millis_t last_rx_ms; // Last time a good packet seen 57 | 58 | uint8_t errorFlag; 59 | }; 60 | 61 | face_t faces[IR_FACE_COUNT]; 62 | 63 | void loopEntry( loopstate_in_t const *loopstate_in , loopstate_out_t *loopstate_out) { 64 | 65 | millis_t now_ms = loopstate_in->millis; 66 | 67 | // Clear out any errors on button press 68 | 69 | if ( loopstate_in->buttonstate.bitflags & BUTTON_BITFLAG_PRESSED ) { 70 | 71 | for( uint8_t f=0; f< IR_FACE_COUNT; f++ ) { 72 | 73 | if ( faces[f].errorFlag ) { 74 | 75 | faces[f].errorFlag=0; 76 | 77 | } 78 | 79 | } 80 | 81 | } 82 | 83 | 84 | for( uint8_t f=0; f< IR_FACE_COUNT; f++ ){ 85 | 86 | // Look for received packet.... 87 | 88 | if ( loopstate_in->ir_data_buffers[f].ready_flag ) { 89 | 90 | if ( (loopstate_in->ir_data_buffers[f].len == COOKIE_SIZE ) && !memcmp( loopstate_in->ir_data_buffers[f].data , cookie , COOKIE_SIZE) ) { 91 | 92 | // Got a good packet! 93 | 94 | faces[f].last_rx_ms = now_ms; 95 | 96 | faces[f].next_tx_ms = now_ms; // pong 97 | 98 | } else { 99 | 100 | // Either len or cookie was wrong, so data transmission error 101 | 102 | faces[f].errorFlag = 1; 103 | 104 | } 105 | 106 | } 107 | 108 | // Update shown color 109 | 110 | if (faces[f].errorFlag) { 111 | 112 | // Red on error 113 | loopstate_out->colors[f] = pixelColor_t( 20 , 0, 0 , 1 ); 114 | 115 | } else { 116 | 117 | millis_t elapsed_ms = now_ms - faces[f].last_rx_ms; // Elapsed time since last RX 118 | 119 | if (elapsed_ms < 200) { 120 | 121 | // Less than 200ms since last good RX, so show green 122 | loopstate_out->colors[f] = pixelColor_t( 0 , 20, 0 , 1 ); 123 | 124 | } else if ( elapsed_ms < 500 ) { 125 | 126 | // More then 200ms since last good RX, so show red for 300ms 127 | loopstate_out->colors[f] = pixelColor_t( 0 , 0, 20 , 1 ); 128 | 129 | 130 | } else { 131 | 132 | // Been long enough that we assume no one is there 133 | loopstate_out->colors[f] = pixelColor_t( 0 , 0, 0 , 1 ); 134 | 135 | } 136 | 137 | } 138 | 139 | 140 | if ( faces[f].next_tx_ms < now_ms ) { 141 | 142 | // Time to send on this face 143 | 144 | if (ir_send_userdata( f , cookie , COOKIE_SIZE )) { 145 | 146 | // Schedule a blind send in case we don't see a ping soon 147 | faces[f].next_tx_ms = now_ms + TX_PROBE_TIME_MS; 148 | } 149 | } // for(f) 150 | 151 | 152 | } 153 | 154 | } 155 | 156 | */ -------------------------------------------------------------------------------- /AS7/blink/bareblinkOS/bareblinkOS/pixelcolor.h: -------------------------------------------------------------------------------- 1 | /* 2 | * pixel.h 3 | * 4 | * All the functions for showing colors on the 6 RGB LEDs on the tile face. 5 | * Also timekeeping functions since we use the same timer as for the LEDs. 6 | * 7 | */ 8 | 9 | #ifndef RGB_PIXELCOLOR_H_ 10 | #define RGB_PIXELCOLOR_H_ 11 | // Each pixel has 32 brightness levels for each of the three colors (red,green,blue) 12 | // These brightness levels are normalized to be visually linear with 0=off and 31=max brightness 13 | 14 | // Note use of anonymous union members to let us switch between bitfield and int 15 | // https://stackoverflow.com/questions/2468708/converting-bit-field-to-int 16 | 17 | union pixelColor_t { 18 | 19 | struct { 20 | uint8_t reserved:1; 21 | uint8_t r:5; 22 | uint8_t g:5; 23 | uint8_t b:5; 24 | }; 25 | 26 | uint16_t as_uint16; 27 | 28 | pixelColor_t(); 29 | pixelColor_t(uint8_t r_in , uint8_t g_in, uint8_t b_in ); 30 | pixelColor_t(uint8_t r_in , uint8_t g_in, uint8_t b_in , uint8_t reserverd_in ); 31 | 32 | }; 33 | 34 | inline pixelColor_t::pixelColor_t(uint8_t r_in , uint8_t g_in, uint8_t b_in ) { 35 | 36 | r=r_in; 37 | g=g_in; 38 | b=b_in; 39 | 40 | } 41 | 42 | inline pixelColor_t::pixelColor_t(uint8_t r_in , uint8_t g_in, uint8_t b_in , uint8_t reserverd_in ) { 43 | 44 | r=r_in; 45 | g=g_in; 46 | b=b_in; 47 | reserved = reserverd_in; 48 | 49 | } 50 | 51 | 52 | inline pixelColor_t::pixelColor_t() { 53 | 54 | r=0; 55 | g=0; 56 | b=0; 57 | 58 | } 59 | 60 | 61 | #endif /* RGB_PIXELS_H_ */ -------------------------------------------------------------------------------- /AS7/blink/blink.atsln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Atmel Studio Solution File, Format Version 11.00 4 | VisualStudioVersion = 14.0.23107.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{E66E83B9-2572-4076-B26E-6BE79FF3018A}") = "Blink", "Sketches\Blink\Blink.cppproj", "{C3728EB0-DD95-4D36-9694-C16A953BBF73}" 7 | EndProject 8 | Project("{E66E83B9-2572-4076-B26E-6BE79FF3018A}") = "blinklib", "..\blinklib\blinklib\blinklib.cppproj", "{1D617D28-32B2-45AB-BA7F-EE884B221598}" 9 | EndProject 10 | Project("{E66E83B9-2572-4076-B26E-6BE79FF3018A}") = "bareblinkOS", "bareblinkOS\bareblinkOS\bareblinkOS.cppproj", "{B750FA7B-22DE-43C4-A796-F95418271EDD}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|AVR = Debug|AVR 15 | Release|AVR = Release|AVR 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {C3728EB0-DD95-4D36-9694-C16A953BBF73}.Debug|AVR.ActiveCfg = Debug|AVR 19 | {C3728EB0-DD95-4D36-9694-C16A953BBF73}.Debug|AVR.Build.0 = Debug|AVR 20 | {C3728EB0-DD95-4D36-9694-C16A953BBF73}.Release|AVR.ActiveCfg = Release|AVR 21 | {C3728EB0-DD95-4D36-9694-C16A953BBF73}.Release|AVR.Build.0 = Release|AVR 22 | {1D617D28-32B2-45AB-BA7F-EE884B221598}.Debug|AVR.ActiveCfg = Debug|AVR 23 | {1D617D28-32B2-45AB-BA7F-EE884B221598}.Debug|AVR.Build.0 = Debug|AVR 24 | {1D617D28-32B2-45AB-BA7F-EE884B221598}.Release|AVR.ActiveCfg = Release|AVR 25 | {1D617D28-32B2-45AB-BA7F-EE884B221598}.Release|AVR.Build.0 = Release|AVR 26 | {B750FA7B-22DE-43C4-A796-F95418271EDD}.Debug|AVR.ActiveCfg = Debug|AVR 27 | {B750FA7B-22DE-43C4-A796-F95418271EDD}.Debug|AVR.Build.0 = Debug|AVR 28 | {B750FA7B-22DE-43C4-A796-F95418271EDD}.Release|AVR.ActiveCfg = Release|AVR 29 | {B750FA7B-22DE-43C4-A796-F95418271EDD}.Release|AVR.Build.0 = Release|AVR 30 | EndGlobalSection 31 | GlobalSection(SolutionProperties) = preSolution 32 | HideSolutionNode = FALSE 33 | EndGlobalSection 34 | EndGlobal 35 | -------------------------------------------------------------------------------- /AS7/blink/blinkcore/blinkcore.componentinfo.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | Device 8 | Startup 9 | 10 | 11 | Atmel 12 | 1.2.0 13 | C:/Program Files (x86)\Atmel\Studio\7.0\Packs 14 | 15 | 16 | 17 | 18 | C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.2.209\include 19 | 20 | include 21 | C 22 | 23 | 24 | include 25 | 26 | 27 | 28 | 29 | C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.2.209\include\avr\iom168pb.h 30 | 31 | header 32 | C 33 | yAkfp/rOk1YuAUNFypsCqg== 34 | 35 | include/avr/iom168pb.h 36 | 37 | 38 | 39 | 40 | C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.2.209\templates\library.c 41 | template 42 | source 43 | C Lib 44 | 2/NZD/YM3hWVTzqme3bDXw== 45 | 46 | templates/library.c 47 | Main file (.c) 48 | 49 | 50 | 51 | C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.2.209\templates\library.cpp 52 | template 53 | source 54 | C Lib 55 | Ztu2zWWQnYWBswuEN+3iHQ== 56 | 57 | templates/library.cpp 58 | Main file (.cpp) 59 | 60 | 61 | 62 | C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.2.209\gcc\dev\atmega168pb 63 | 64 | libraryPrefix 65 | GCC 66 | 67 | 68 | gcc/dev/atmega168pb 69 | 70 | 71 | 72 | 73 | ATmega_DFP 74 | C:/Program Files (x86)/Atmel/Studio/7.0/Packs/atmel/ATmega_DFP/1.2.209/Atmel.ATmega_DFP.pdsc 75 | 1.2.209 76 | true 77 | ATmega168PB 78 | 79 | 80 | 81 | Resolved 82 | Fixed 83 | true 84 | 85 | 86 | -------------------------------------------------------------------------------- /AS7/blink/blinklib/WMath.cpp: -------------------------------------------------------------------------------- 1 | /* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */ 2 | 3 | /* 4 | Part of the Wiring project - http://wiring.org.co 5 | Copyright (c) 2004-06 Hernando Barragan 6 | Modified 13 August 2006, David A. Mellis for Arduino - http://www.arduino.cc/ 7 | 8 | This library is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU Lesser General Public 10 | License as published by the Free Software Foundation; either 11 | version 2.1 of the License, or (at your option) any later version. 12 | This library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | Lesser General Public License for more details. 16 | You should have received a copy of the GNU Lesser General 17 | Public License along with this library; if not, write to the 18 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, 19 | Boston, MA 02111-1307 USA 20 | 21 | */ 22 | 23 | extern "C" { 24 | #include "stdlib.h" 25 | } 26 | 27 | void randomSeed(unsigned long seed) 28 | { 29 | if (seed != 0) { 30 | srandom(seed); 31 | } 32 | } 33 | 34 | long random(long howbig) 35 | { 36 | if (howbig == 0) { 37 | return 0; 38 | } 39 | return random() % howbig; 40 | } 41 | 42 | long random(long howsmall, long howbig) 43 | { 44 | if (howsmall >= howbig) { 45 | return howsmall; 46 | } 47 | long diff = howbig - howsmall; 48 | return random(diff) + howsmall; 49 | } 50 | 51 | long map(long x, long in_min, long in_max, long out_min, long out_max) 52 | { 53 | return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; 54 | } 55 | 56 | unsigned int makeWord(unsigned int w) { return w; } 57 | unsigned int makeWord(unsigned char h, unsigned char l) { return (h << 8) | l; } -------------------------------------------------------------------------------- /AS7/blink/blinklib/blinkos.componentinfo.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | Device 8 | Startup 9 | 10 | 11 | Atmel 12 | 1.2.0 13 | C:/Program Files (x86)\Atmel\Studio\7.0\Packs 14 | 15 | 16 | 17 | 18 | C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.2.209\include 19 | 20 | include 21 | C 22 | 23 | 24 | include 25 | 26 | 27 | 28 | 29 | C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.2.209\include\avr\iom168pb.h 30 | 31 | header 32 | C 33 | yAkfp/rOk1YuAUNFypsCqg== 34 | 35 | include/avr/iom168pb.h 36 | 37 | 38 | 39 | 40 | C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.2.209\templates\library.c 41 | template 42 | source 43 | C Lib 44 | 2/NZD/YM3hWVTzqme3bDXw== 45 | 46 | templates/library.c 47 | Main file (.c) 48 | 49 | 50 | 51 | C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.2.209\templates\library.cpp 52 | template 53 | source 54 | C Lib 55 | Ztu2zWWQnYWBswuEN+3iHQ== 56 | 57 | templates/library.cpp 58 | Main file (.cpp) 59 | 60 | 61 | 62 | C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.2.209\gcc\dev\atmega168pb 63 | 64 | libraryPrefix 65 | GCC 66 | 67 | 68 | gcc/dev/atmega168pb 69 | 70 | 71 | 72 | 73 | ATmega_DFP 74 | C:/Program Files (x86)/Atmel/Studio/7.0/Packs/atmel/ATmega_DFP/1.2.209/Atmel.ATmega_DFP.pdsc 75 | 1.2.209 76 | true 77 | ATmega168PB 78 | 79 | 80 | 81 | Resolved 82 | Fixed 83 | true 84 | 85 | 86 | -------------------------------------------------------------------------------- /AS7/blink/blinkstate/blinklib.componentinfo.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | Device 8 | Startup 9 | 10 | 11 | Atmel 12 | 1.2.0 13 | C:/Program Files (x86)\Atmel\Studio\7.0\Packs 14 | 15 | 16 | 17 | 18 | C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.2.209\include 19 | 20 | include 21 | C 22 | 23 | 24 | include 25 | 26 | 27 | 28 | 29 | C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.2.209\include\avr\iom168pb.h 30 | 31 | header 32 | C 33 | yAkfp/rOk1YuAUNFypsCqg== 34 | 35 | include/avr/iom168pb.h 36 | 37 | 38 | 39 | 40 | C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.2.209\templates\library.c 41 | template 42 | source 43 | C Lib 44 | 2/NZD/YM3hWVTzqme3bDXw== 45 | 46 | templates/library.c 47 | Main file (.c) 48 | 49 | 50 | 51 | C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.2.209\templates\library.cpp 52 | template 53 | source 54 | C Lib 55 | Ztu2zWWQnYWBswuEN+3iHQ== 56 | 57 | templates/library.cpp 58 | Main file (.cpp) 59 | 60 | 61 | 62 | C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.2.209\gcc\dev\atmega168pb 63 | 64 | libraryPrefix 65 | GCC 66 | 67 | 68 | gcc/dev/atmega168pb 69 | 70 | 71 | 72 | 73 | ATmega_DFP 74 | C:/Program Files (x86)/Atmel/Studio/7.0/Packs/atmel/ATmega_DFP/1.2.209/Atmel.ATmega_DFP.pdsc 75 | 1.2.209 76 | true 77 | ATmega168PB 78 | 79 | 80 | 81 | Resolved 82 | Fixed 83 | true 84 | 85 | 86 | -------------------------------------------------------------------------------- /AS7/blink/blinkstate/blinklib.cppproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 2.0 5 | 7.0 6 | com.Atmel.AVRGCC8.CPP 7 | {c7103c5c-377a-4589-89b5-ee449b21a39a} 8 | ATmega168PB 9 | none 10 | StaticLibrary 11 | CPP 12 | lib$(MSBuildProjectName) 13 | .a 14 | $(MSBuildProjectDirectory)\$(Configuration) 15 | 16 | 17 | blinkstate 18 | blinklib 19 | blinkstate 20 | Native 21 | true 22 | false 23 | true 24 | true 25 | 26 | 27 | true 28 | 29 | 2 30 | 0 31 | 0 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | -mmcu=atmega168pb -B "%24(PackRepoDir)\atmel\ATmega_DFP\1.2.209\gcc\dev\atmega168pb" 54 | True 55 | True 56 | True 57 | True 58 | False 59 | True 60 | True 61 | 62 | 63 | NDEBUG 64 | 65 | 66 | 67 | 68 | %24(PackRepoDir)\atmel\ATmega_DFP\1.2.209\include 69 | 70 | 71 | Optimize for size (-Os) 72 | True 73 | True 74 | True 75 | True 76 | True 77 | 78 | 79 | NDEBUG 80 | 81 | 82 | 83 | 84 | %24(PackRepoDir)\atmel\ATmega_DFP\1.2.209\include 85 | 86 | 87 | Optimize for size (-Os) 88 | True 89 | True 90 | True 91 | 92 | 93 | libm 94 | 95 | 96 | 97 | 98 | %24(PackRepoDir)\atmel\ATmega_DFP\1.2.209\include 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | -mmcu=atmega168pb -B "%24(PackRepoDir)\atmel\ATmega_DFP\1.2.209\gcc\dev\atmega168pb" 108 | True 109 | True 110 | True 111 | True 112 | False 113 | True 114 | True 115 | 116 | 117 | DEBUG 118 | 119 | 120 | 121 | 122 | ../../../../variants/standard 123 | %24(PackRepoDir)\atmel\ATmega_DFP\1.2.209\include 124 | 125 | 126 | Optimize (-O1) 127 | True 128 | True 129 | Default (-g2) 130 | True 131 | True 132 | True 133 | 134 | 135 | DEBUG 136 | 137 | 138 | 139 | 140 | ../../../../libraries/blinklib/src 141 | ../../../../cores/blinkcore 142 | %24(PackRepoDir)\atmel\ATmega_DFP\1.2.209\include 143 | 144 | 145 | Optimize (-O1) 146 | True 147 | True 148 | Default (-g2) 149 | True 150 | 151 | 152 | libm 153 | 154 | 155 | 156 | 157 | %24(PackRepoDir)\atmel\ATmega_DFP\1.2.209\include 158 | 159 | 160 | Default (-Wa,-g) 161 | 162 | 163 | 164 | 165 | -------------------------------------------------------------------------------- /AS7/blinklib/blinklib/blinklib.componentinfo.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | Device 8 | Startup 9 | 10 | 11 | Atmel 12 | 1.2.0 13 | C:/Program Files (x86)\Atmel\Studio\7.0\Packs 14 | 15 | 16 | 17 | 18 | C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.2.209\include 19 | 20 | include 21 | C 22 | 23 | 24 | include 25 | 26 | 27 | 28 | 29 | C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.2.209\include\avr\iom168pb.h 30 | 31 | header 32 | C 33 | yAkfp/rOk1YuAUNFypsCqg== 34 | 35 | include/avr/iom168pb.h 36 | 37 | 38 | 39 | 40 | C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.2.209\templates\library.c 41 | template 42 | source 43 | C Lib 44 | 2/NZD/YM3hWVTzqme3bDXw== 45 | 46 | templates/library.c 47 | Main file (.c) 48 | 49 | 50 | 51 | C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.2.209\templates\library.cpp 52 | template 53 | source 54 | C Lib 55 | XxwIOzelgjmEqvoplf+/zA== 56 | 57 | templates/library.cpp 58 | Main file (.cpp) 59 | 60 | 61 | 62 | C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.2.209\gcc\dev\atmega168pb 63 | 64 | libraryPrefix 65 | GCC 66 | 67 | 68 | gcc/dev/atmega168pb 69 | 70 | 71 | 72 | 73 | ATmega_DFP 74 | C:/Program Files (x86)/Atmel/Studio/7.0/Packs/atmel/ATmega_DFP/1.2.209/Atmel.ATmega_DFP.pdsc 75 | 1.2.209 76 | true 77 | ATmega168PB 78 | 79 | 80 | 81 | Resolved 82 | Fixed 83 | true 84 | 85 | 86 | -------------------------------------------------------------------------------- /AS7/blinkos/blinkos/blinkos.componentinfo.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | Device 8 | Startup 9 | 10 | 11 | Atmel 12 | 1.2.0 13 | C:/Program Files (x86)\Atmel\Studio\7.0\Packs 14 | 15 | 16 | 17 | 18 | C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.2.209\include 19 | 20 | include 21 | C 22 | 23 | 24 | include 25 | 26 | 27 | 28 | 29 | C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.2.209\include\avr\iom168pb.h 30 | 31 | header 32 | C 33 | yAkfp/rOk1YuAUNFypsCqg== 34 | 35 | include/avr/iom168pb.h 36 | 37 | 38 | 39 | 40 | C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.2.209\templates\library.c 41 | template 42 | source 43 | C Lib 44 | 2/NZD/YM3hWVTzqme3bDXw== 45 | 46 | templates/library.c 47 | Main file (.c) 48 | 49 | 50 | 51 | C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.2.209\templates\library.cpp 52 | template 53 | source 54 | C Lib 55 | k0XODgvtMPZr5NdihYUf6A== 56 | 57 | templates/library.cpp 58 | Main file (.cpp) 59 | 60 | 61 | 62 | C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.2.209\gcc\dev\atmega168pb 63 | 64 | libraryPrefix 65 | GCC 66 | 67 | 68 | gcc/dev/atmega168pb 69 | 70 | 71 | 72 | 73 | ATmega_DFP 74 | C:/Program Files (x86)/Atmel/Studio/7.0/Packs/atmel/ATmega_DFP/1.2.209/Atmel.ATmega_DFP.pdsc 75 | 1.2.209 76 | true 77 | ATmega168PB 78 | 79 | 80 | 81 | Resolved 82 | Fixed 83 | true 84 | 85 | 86 | -------------------------------------------------------------------------------- /Getting-started.md: -------------------------------------------------------------------------------- 1 | 2 | ## Getting Started 3 | 4 | This core requires at least Arduino IDE v1.6.2, where v1.6.5+ is recommended.
5 | * [Programmers](#programmers) 6 | * **[How to install](#how-to-install)** 7 | - [Boards Manager Installation](#boards-manager-installation) 8 | - [Manual Installation](#manual-installation) 9 | * **[Getting started](#getting-started)** 10 | 11 | * **[Digging deeper](#digging-deeper)** 12 | - [Hardware Abstraction Layer](#hardware-abstraction-layer) 13 | 14 | ## Programmers 15 | 16 | Since there is no bootloader in a tile, all code must be programmed rather than downloaded. 17 | 18 | Each Blink has a standard 6-pin ISP connector. The arrow marks pin #1. 19 | 20 | You can use any AVR programmer supported by AVRDUDE and the Arduino IDE. 21 | 22 | This one is cheap... 23 | http://amzn.to/2u5ZHw6 24 | 25 | This one is fast and comes with nice cables... 26 | http://amzn.to/2u5Wo7M 27 | 28 | Just connect your programmer and select it in the "Programmers" menu, and connect the 6-pin ISP to the tile. I like to use this pogo pin fixture to make the connections... 29 | 30 | https://www.sparkfun.com/products/11591 31 | 32 | ...but you can also just hold a 6-pin header onto the tile, or solder on a 6-pin header if you want to leave the programmer attached. 33 | 34 | If you do not have a programmer, you can also use an Arduino and a couple of wires. 35 | 36 | You can then use the "Sketch-Upload to Programmer" menu choice or just press the Play button to compile your code and program it into the connected tile. (Both the menu option and the button do the same thing with a tile.) 37 | 38 | ## How to install 39 | Click on the "Download ZIP" button in the upper right corner of this repo on Github... 40 | 41 | https://github.com/bigjosh/Move38-Arduino-Platform 42 | 43 | You can switch to the `dev` branch if you want to live on the bleeding edge and get new features quickly. 44 | 45 | Extract the ZIP file, and move the extracted files to the location "**~/Documents/Arduino/hardware/Move38-manual/avr**". Create the folder if it doesn't exist. This readme file should be located at "**~/Documents/Arduino/hardware/Move38-manual/avr/README.md**" when you are done. 46 | 47 | Open Arduino IDE, and a new category in the boards menu called "Move38-manual" will show up. 48 | 49 | ##### Notes 50 | 51 | * We called the "vendor/maintainer" folder `Move38-manual` so that you can also use the boards manager and you will be able to tell the two apart in the boards menu. 52 | 53 | * You must manually create the `avr` folder and you must also manually move the files out from this repo into this folder. We could not automatically have the folds inside the repo match the Arduino required folder layout because in in the boards manager, the architecture is in the JSON file rather than the folder structure. Arg. 54 | 55 | * The "**~/Documents/Arduino/hardware/Move38-manual/avr**" folder is a Git repo and is also set up for easy editing in Atmel Studio with a solution inside the `\AS7` sub-folder. 56 | 57 | * If you want to leave the git repo in a directory that is not inside the Arduino tree (I do), then you can add a directory symlink from the Arduino tree to the repo tree. This repo needs to be at `arduino\hardware\move38\avr` where `arduino` is your Arduino home directory as set in `File->Preferences->Sketchbook Location` in the IDE. You have to manually create `hardware` and then `move38` and then put the `avr` symlink in then. On my windows machine the command for that was `D:\Documents\Arduino\hardware\move38\avr>mklink /D avr "D:\Github\Move38-Arduino-Platform"` 58 | 59 | ## Helllo Blink! 60 | 61 | * Open the **Tools > Board** menu item, and select `Blink` from the `Move38` submenu. 62 | * Select what kind of programmer you're using under the **Programmers** menu. 63 | * Select "File->Examples->Examples for Blink->Getting Started" and choose "F-ColorWheel". 64 | * Hit the Play button. 65 | 66 | The IDE should compile the code and program the Blinks tile... and you should see pretty blinking lights! 67 | -------------------------------------------------------------------------------- /Layers.md: -------------------------------------------------------------------------------- 1 | ## Layers 2 | 3 | ### 1. Cold power up 4 | 5 | This typically only happens when a new battery is installed or when the foreground software locks up. 6 | 7 | The chip resets all the ports according to the the datasheet and then jumps to the reset vector, which typically points to the GCC bootstrap code. This code initializes global variables and does a bit of hardware setup. 8 | 9 | Here is an example on how to run code before the bootstrap (very esoteric)... 10 | 11 | https://github.com/bigjosh/Ognite-firmware/blob/master/Atmel%20Studio/Candle0005.c#L440 12 | 13 | ### 2. main() 14 | 15 | After all the C setup is complete, the bootstrap jumps to the `main()` function. This function is in `cores/blinkcore/main.c` 16 | 17 | Here we... 18 | 19 | 1. Initialize the binks hardware systems and turn them on. 20 | 2. Jump to the `run()` function. 21 | 3. Re-run `run()` forever if it returns. 22 | 23 | The blinks `main()` function is weakly defined, so you can make your own if you want to take over before the blinks hardware gets started up. 24 | 25 | ### 3. run() 26 | 27 | Once all the hardware is up and running, then `run()` function takes over. This code lives in `libraries\blinklib\src\blinklib.cpp`. 28 | 29 | Here we... 30 | 31 | 1. Call the user-supplied `setup()` function. 32 | 2. Repeatedly... 33 | a. Clears the cached `millis()` snapshot 34 | b. Calls the user-suppled `loop()` function 35 | c. Atomically updates the values shown on the LEDs to match any changes made in `loop()` 36 | d. Processes new IR data that has been recieved, and potentially sends IR data. 37 | 38 | 39 | Then `run()` function is weakly defined, so you can override it if you want more control over these. 40 | 41 | ### 4. `setup()` and `loop()` 42 | 43 | These are the idiomatic entry points provided by Arduino sketches. 44 | 45 | `setup()` is called once, typically right after a tile has had a battery change. 46 | 47 | `loop()` is called at the current frame rate, which is currently about 18 times per second. You `loop()` function should complete before the next frame starts, so should not have any blocking code in it. The tile sleeps for the time between when `loop()` returns and the next frame, so the faster you can complete your work and return from loop, the longer batteries will last. 48 | 49 | 50 | -------------------------------------------------------------------------------- /Production.MD: -------------------------------------------------------------------------------- 1 | ## Production Programming 2 | 3 | Each virgin blink needs to be programmed with... 4 | 5 | 1. The correct FUSE settings 6 | 2. The BIOS code that lives in the flash bootloader area 7 | 3. The application code that lives in the application flash area. 8 | 9 | ### Fuses 10 | 11 | BOOTSZ = 1024W_1C00 12 | BOOTRST = [X] 13 | RSTDISBL = [ ] 14 | DWEN = [ ] 15 | SPIEN = [X] 16 | WDTON = [ ] 17 | EESAVE = [ ] 18 | BODLEVEL = DISABLED 19 | CKDIV8 = [X] 20 | CKOUT = [ ] 21 | SUT_CKSEL = INTRCOSC_8MHZ_6CK_14CK_65MS 22 | 23 | EXTENDED = 0xF8 (valid) 24 | HIGH = 0xDF (valid) 25 | LOW = 0x62 (valid) 26 | 27 | Note that the `high` and `low` fuses are the same as their default values from the factory, but the `extended` fuse must be reprogrammed from the default value. 28 | 29 | ### Bootloader 30 | 31 | The bootloader code comes from a different repo and can be found in the [`bootloaders`](/bootloaders) directory here. 32 | 33 | ### Application 34 | 35 | The application code is generated by compiling a sketch in the Arduino IDE. 36 | 37 | ## Combining the bootloader and application 38 | 39 | You can minimize the number of production programming steps by combining the application code and bootloader into a single HEX file using the `Sketch->Export Compiled Binary` option from the IDE menus. This will create a file called `SKETCHNAME.ino.with_bootloader.standard.hex` in the current sketch folder that contains both the application and the bootloader. 40 | 41 | ### Example 42 | 43 | Here is and example command that will program a blink using the `AVRDUDE` utility and the `USBtiny` programmer... 44 | 45 | ``` 46 | avrdude -B 5 -v -patmega168pb -cusbtiny -Uflash:w:SKETCHNAME.ino.with_bootloader.standard.hex:i -Uefuse:w:0xf8:m -u 47 | ``` 48 | 49 | `-B` sets the clock programming speed. This must be less than 1/4 of the chip clock speed, which is 1Mhz by default, but here we make it slightly slower to account for chips that might have an extra slow internal clock. 50 | `-v` verifies the programming when complete 51 | `-p` specifies the chip model 52 | `-Uflash` specifies the file to program into flash memory (both bootloader and application in this case) 53 | `-Uefuse` specifies the new value for the extended fuse (note that the high and low fuses are left with their default values) 54 | `-u` disables AVRDUDE's normal behavior that blocks changing fuses. 55 | 56 | Note that this assumes that `avrdude` is in your search path and that it can find its config file. See `avrdude` docs for details. 57 | 58 | ### Optimizing 59 | 60 | We can slightly reduce cycle using a command like this... 61 | 62 | ``` 63 | avrdude -B 4 -D -v -patmega168pb -cusbtiny -Uflash:w:D-TimerFlashX.ino.with_bootloader.standard.hex:i -Uefuse:w:0xf8:m -u 64 | ``` 65 | 66 | `-D` skips erasing the flash before programming it. If you are programming virgin chips then the flash should be blank. 67 | `-B` lowered to 4 slightly increases the programmer clock. Some out of spec chips might fall to program at this speed. 68 | 69 | Note that these new options are both safe because the verify will fail if anything goes wrong. 70 | 71 | ### QA 72 | 73 | Some programming errors may pass functional testing, but still contain latent errors, so you must check that the programming cycle verified successfully before passing a programmed unit. 74 | 75 | You can use the error code returned by AVRDUDE to check if the verify succeeded. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Move38 Blinks for the Arduino IDE 2 | An Arduino core for the Blinks gaming tile. More info at... 3 | http://move38.com 4 | 5 | ## Roadmap 6 | 7 | This core requires at least Arduino IDE v1.6.2, where v1.6.5+ is recommended.
8 | * [Programmers](#programmers) 9 | * **[How to install](#how-to-install)** 10 | * **[Getting started](#getting-started)** 11 | 12 | Covers installing this repo so that you can write and download code into a Blinks tile using the Arduino IDE. 13 | 14 | Ends with loading a `HelloBlink` program it a tile. 15 | 16 | ### Writing games 17 | 18 | The best way to start writing games is to work your way though the examples in the "File->Examples->Examples for Blink Tile" menu in the Arduino IDE (after you have installed this repo as described in the Getting Started above). 19 | 20 | 21 | ### [Service Port](Service Port.MD) 22 | 23 | Describes the service port connector on each blink. Lets you add `print` statements to your programs, which can be very helpful during development. 24 | 25 | ## How to install 26 | 27 | Click on the "Download ZIP" button in the upper right corner of this repo. Extract the ZIP file, and move the extracted files to the location "**~/Documents/Arduino/hardware/Move38-manual/avr**". Create the folder if it doesn't exist. This readme file should be located at "**~/Documents/Arduino/hardware/Move38-manual/avr/README.md**" when you are done. 28 | 29 | Open Arduino IDE, and a new category in the boards menu called "Move38-manual" will show up. 30 | 31 | In the future, we'll offer a simplified Arduino Boards Manager install path. 32 | 33 | ### Notes 34 | 35 | * We called the "vendor/maintainer" folder `Move38-manual` so that you can also use the boards manager and you will be able to tell the two apart in the boards menu. 36 | 37 | * You must manually create the `avr` folder and you must also manually move the files out from this repo into this folder. We could not automatically have the folds inside the repo match the Arduino required folder layout because in in the boards manager, the architecture is in the JSON file rather than the folder structure. Arg. 38 | 39 | * The "**~/Documents/Arduino/hardware/Move38-manual/avr**" folder is a Git repo and is also set up for easy editing in Atmel Studio with a solution inside the `\AS7` sub-folder. 40 | 41 | ### API Layers 42 | 43 | The blinks hardware can do incredible things, and you can have unfettered access to it at any level you want. This documents describes those layers from bare metal up. 44 | 45 | 46 | 47 | #### Hardware Abstraction Layer 48 | 49 | Most programmers will want to use the high level `blinks` API, but if you want to get closer to the hardware you can directly call into the `HAL` (Hardware Abstraction Layer) that the `blinks` API is built on top of. Documentation for this layer is in the [README.md](cores/blinkcore/README.md) in the `cores/blinkscore` folder. 50 | -------------------------------------------------------------------------------- /Service Port.MD: -------------------------------------------------------------------------------- 1 | 2 | > *"The most effective debugging tool is still careful thought, coupled with judiciously placed print statements."* 3 | 4 | -Brian Kernighan, "Unix for Beginners" (1979) 5 | 6 | 7 | #### Service Port 8 | 9 | Each Blink tile has a service port to make developing and debugging easier. For example: 10 | 11 | * See print statements 12 | * Accept type in values and commands 13 | * Output precise timing signals to an oscilloscope 14 | 15 | 16 | ### Seeing output 17 | 18 | When writing normal game code, you can use the the service port as a serial connection to the host computer. 19 | 20 | #### Connection 21 | 22 | Get yourself a Blinks Dev Candy board, which converts the service port connector into a 6-pin header that connects to a USB serial converter like this... 23 | 24 | http://amzn.to/2ptPUv5 25 | 26 | #### Use 27 | 28 | * Connect the USB serial port adapter to the computer 29 | * Open Arduino IDE 30 | * Pick the correct serial port from `Tools->Port` 31 | * Open the monitor with "Tools->Serial Port Monitor" 32 | * Pick `1000000 baud`. (Yes, it is that fast! :) ) 33 | 34 | You will now see anything that the tile prints out. 35 | 36 | You can also use any other serial monitor program with the same port and baud settings. 37 | 38 | #### Instrumentation 39 | 40 | The easiest way to get prints out the serial port is to use the `ServicePortSerial` class like this... 41 | 42 | ~~~ 43 | /* 44 | * Prints a welcoming message to the servie port. 45 | * 46 | * To see the message, connect a serial terminal to the Blinks service port. 47 | * More info on how to do that here... 48 | * https://github.com/bigjosh/Move38-Arduino-Platform/blob/master/Service%20Port.MD 49 | */ 50 | 51 | #include "Serial.h" 52 | 53 | ServicePortSerial Serial; 54 | 55 | void setup() { 56 | 57 | Serial.begin(); 58 | 59 | } 60 | 61 | 62 | void loop() { 63 | 64 | Serial.println("Hello Serial port!"); 65 | 66 | }; 67 | ~~~ 68 | 69 | #### Input 70 | 71 | The Serial class also has several read functions that let you input data from the serial terminal. Check out the Tile World example to see one way to do this. 72 | 73 | Note that that by default Arduino serial monitor does not send what you type until you press enter. -------------------------------------------------------------------------------- /Tools.md: -------------------------------------------------------------------------------- 1 | # Tools 2 | ## Programmers 3 | - Pocket AVR Programmer - [$14.95 on Sparkfun](https://www.sparkfun.com/products/9825) 4 | - ISP Pogo Adapter - [$9.95 on Sparkfun](https://www.sparkfun.com/products/11591) 5 | - ISP Pogo Adapter - [$6.50 on Tindie](https://www.tindie.com/products/madworm/tiny-avr-isp-pogo-pin-programming-adapter/) 6 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-minimal -------------------------------------------------------------------------------- /boards.txt: -------------------------------------------------------------------------------- 1 | # See: http://code.google.com/p/arduino/wiki/Platforms 2 | 3 | menu.cpu=Processor 4 | 5 | ############################################################## 6 | 7 | blink.name=Blink 8 | 9 | blink.vid.0=0x2341 10 | blink.pid.0=0x0043 11 | blink.vid.1=0x2341 12 | blink.pid.1=0x0001 13 | blink.vid.2=0x2A03 14 | blink.pid.2=0x0043 15 | blink.vid.3=0x2341 16 | blink.pid.3=0x0243 17 | 18 | blink.upload.tool=avrdude 19 | blink.upload.protocol=arduino 20 | 21 | # This is the maximum size of a program image. It comes from 22 | # `blinkbios.h` and is the result of `FLASH_PAGES_PER_IMAGE` * `FLASH_BYTES_PER_PAGE` 23 | # Used only for printing the "Sketch uses... of program stroage space..." message. 24 | blink.upload.maximum_size=5888 25 | blink.upload.maximum_data_size=1024 26 | blink.upload.speed=115200 27 | 28 | #blink.bootloader.tool=avrdude 29 | #blink.bootloader.low_fuses=0xFF 30 | #blink.bootloader.high_fuses=0xDE 31 | #blink.bootloader.extended_fuses=0xFD 32 | #blink.bootloader.unlock_bits=0x3F 33 | #blink.bootloader.lock_bits=0x0F 34 | 35 | # Note that the folder `bootloaders` seems to be hardcoded into the Ardunio IDE 36 | 37 | blink.bootloader.file=BlinkBIOS.hex 38 | 39 | blink.build.mcu=atmega168pb 40 | blink.build.f_cpu=8000000L 41 | blink.build.board=AVR_BLINK 42 | blink.build.core=blinklib 43 | blink.build.variant=standard 44 | 45 | ############################################################## 46 | 47 | -------------------------------------------------------------------------------- /bootloaders/readme.MD: -------------------------------------------------------------------------------- 1 | This folder contains the BlinkBIOS bootloader HEX file. This file is created by the BlinkBIOS repo... 2 | 3 | https://github.com/bigjosh/Move38-BlinkBIOS 4 | 5 | ..and then copied here after each compile by an Atmel Studio post-build event. Note that the this bootloader directory is hardcoded into the text of that event. 6 | 7 | This file is used by... 8 | 9 | 1. The `upload` and `program` recipes to download a new sketch to a blink. Note that we could make upload only update the actual program and not the BIOS for faster turnaround during development, but I do not want to change this behavior now. The path to the bootloader is hardcoded into the recipes but is relative to the platform folder. 10 | 2. The `Export Binary` function which creates a single HEX file with both the current sketch and the BIOS. In this case, the folder name must be `bootloader` as this is hardcoded into the IDE. 11 | 12 | 13 | -------------------------------------------------------------------------------- /cores/blinklib/Arduino.h: -------------------------------------------------------------------------------- 1 | // Reworked for Blinks platform. 2 | // Really should be renamed Blinks.h, but Arduino.h seems to be hardcoded lots of places. 3 | 4 | /* 5 | Arduino.h - Main include file for the Arduino SDK 6 | Copyright (c) 2005-2013 Arduino Team. All right reserved. 7 | 8 | This library is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU Lesser General Public 10 | License as published by the Free Software Foundation; either 11 | version 2.1 of the License, or (at your option) any later version. 12 | 13 | This library is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | Lesser General Public License for more details. 17 | 18 | You should have received a copy of the GNU Lesser General Public 19 | License along with this library; if not, write to the Free Software 20 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 | */ 22 | 23 | 24 | #ifndef Arduino_h 25 | 26 | #define Arduino_h 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | #include "ArduinoTypes.h" 33 | 34 | #define HIGH 0x1 35 | #define LOW 0x0 36 | 37 | #define PI 3.1415926535897932384626433832795 38 | #define HALF_PI 1.5707963267948966192313216916398 39 | #define TWO_PI 6.283185307179586476925286766559 40 | #define DEG_TO_RAD 0.017453292519943295769236907684886 41 | #define RAD_TO_DEG 57.295779513082320876798154814105 42 | #define EULER 2.718281828459045235360287471352 43 | 44 | 45 | #define LSBFIRST 0 46 | #define MSBFIRST 1 47 | 48 | // undefine stdlib's abs if encountered 49 | #ifdef abs 50 | #undef abs 51 | #endif 52 | 53 | #define min(a,b) ((a)<(b)?(a):(b)) 54 | #define max(a,b) ((a)>(b)?(a):(b)) 55 | #define abs(x) ((x)>0?(x):-(x)) 56 | #define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt))) 57 | #define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5)) 58 | #define radians(deg) ((deg)*DEG_TO_RAD) 59 | #define degrees(rad) ((rad)*RAD_TO_DEG) 60 | #define sq(x) ((x)*(x)) 61 | 62 | #define lowByte(w) ((uint8_t) ((w) & 0xff)) 63 | #define highByte(w) ((uint8_t) ((w) >> 8)) 64 | 65 | #define bitRead(value, bit) (((value) >> (bit)) & 0x01) 66 | #define bitSet(value, bit) ((value) |= (1UL << (bit))) 67 | #define bitClear(value, bit) ((value) &= ~(1UL << (bit))) 68 | #define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit)) 69 | 70 | #define bit(b) (1UL << (b)) 71 | 72 | // Don't judge me 73 | // I know this is so ugly, but only other way to make it so people do not need to do a 74 | // manual #include in their sketches would be to throw all the library code into one giant 75 | // directory... and that is even uglier, right? 76 | 77 | #include "blinklib.h" 78 | 79 | #endif 80 | -------------------------------------------------------------------------------- /cores/blinklib/ArduinoTypes.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Some types used in idiomatic Arduino code and Arduino compatible function signatures. 4 | We break them out into thier own header so we can implement against them without having to 5 | include the toxic Arduino.h itself. 6 | 7 | */ 8 | 9 | 10 | #ifndef ArduinoTypes_h 11 | 12 | #define ArduinoTypes_h 13 | 14 | 15 | #include 16 | typedef bool boolean; 17 | typedef uint8_t byte; 18 | typedef unsigned int word; 19 | 20 | typedef uint32_t ulong; 21 | 22 | #endif -------------------------------------------------------------------------------- /cores/blinklib/DummySerial.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | A very simplified serial port built to look like Arduino's Serial class. 4 | 5 | This serial port lives on the service port on new boards. It is really intended for debugging. 6 | 7 | The port always runs at a fixed 1M baud. Dev Candy Adapter boards and cables are available to 8 | connect to a USB port and then use the Arduino IDE's serial monitor to interact with your tile. 9 | 10 | */ 11 | 12 | #include 13 | 14 | #include "ArduinoTypes.h" 15 | 16 | #ifndef Serial_h 17 | 18 | #define Serial_h 19 | 20 | #include "Print.h" 21 | 22 | class ServicePortSerial : public Print 23 | { 24 | 25 | public: 26 | 27 | //inline ServicePortSerialSerial(void); 28 | void begin(void); 29 | void end(); 30 | 31 | virtual int available(void); 32 | 33 | // Input buffer is only 1 byte so if an interrupts happens while data is streaming, you will loose any incoming data. 34 | // Best to limit yourself interactions with plenty of time (or an ACK) between each incoming byte. 35 | 36 | virtual int read(void); // Read a byte - returns byte read or -1 if no byte ready. 37 | virtual uint8_t readWait(void); // Blocking read (faster) 38 | 39 | virtual size_t write(uint8_t); 40 | void flush(void); // Block until all pending transmits complete 41 | 42 | using Print::write; // pull in write(str) and write(buf, size) from Print 43 | 44 | 45 | }; 46 | 47 | #endif 48 | 49 | 50 | 51 | // Public Methods ////////////////////////////////////////////////////////////// 52 | 53 | void ServicePortSerial::begin(void) 54 | { 55 | } 56 | 57 | void ServicePortSerial::end() 58 | { 59 | } 60 | 61 | // We only use the 1 byte hardware buffer 62 | 63 | inline int ServicePortSerial::available(void) { 64 | return(0); 65 | } 66 | 67 | inline int ServicePortSerial::read(void) 68 | { 69 | return -1; 70 | } 71 | 72 | inline byte ServicePortSerial::readWait(void) 73 | { 74 | return 0; 75 | } 76 | 77 | // We don't implement flush because it would require adding a flag to remember if we ever sent. 78 | // This is because the hardware only gives us a bit that tells us when a tx completes, not if 79 | // no TX was ever started. Ardunio does this with the `_writen` flag. 80 | // If you can convince me that we really need flush, LMK and it can be added. 81 | 82 | inline size_t ServicePortSerial::write(uint8_t c) 83 | { 84 | 85 | return(1); 86 | 87 | } 88 | 89 | // Block until all pending transmits complete 90 | 91 | void ServicePortSerial::flush(void) 92 | { 93 | } -------------------------------------------------------------------------------- /cores/blinklib/Print.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | This is a slimed down version of the Arduino Print class for the tiles platform. 4 | Implements most cases except WStrings and Printables 5 | 6 | 7 | Original header: 8 | 9 | Print.cpp - Base class that provides print() and println() 10 | Copyright (c) 2008 David A. Mellis. All right reserved. 11 | 12 | This library is free software; you can redistribute it and/or 13 | modify it under the terms of the GNU Lesser General Public 14 | License as published by the Free Software Foundation; either 15 | version 2.1 of the License, or (at your option) any later version. 16 | 17 | This library is distributed in the hope that it will be useful, 18 | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 | Lesser General Public License for more details. 21 | 22 | You should have received a copy of the GNU Lesser General Public 23 | License along with this library; if not, write to the Free Software 24 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 25 | 26 | Modified 23 November 2006 by David A. Mellis 27 | Modified 03 August 2015 by Chuck Todd 28 | */ 29 | 30 | #include 31 | #include 32 | #include 33 | 34 | #include "Print.h" 35 | 36 | // Public Methods ////////////////////////////////////////////////////////////// 37 | 38 | /* default implementation: may be overridden */ 39 | size_t Print::write(const uint8_t *buffer, size_t size) 40 | { 41 | size_t n = 0; 42 | while (size--) { 43 | if (write(*buffer++)) n++; 44 | else break; 45 | } 46 | return n; 47 | } 48 | 49 | size_t Print::print(const __FlashStringHelper *ifsh) 50 | { 51 | PGM_P p = reinterpret_cast(ifsh); 52 | size_t n = 0; 53 | while (1) { 54 | unsigned char c = pgm_read_byte(p++); 55 | if (c == 0) break; 56 | if (write(c)) n++; 57 | else break; 58 | } 59 | return n; 60 | } 61 | 62 | 63 | size_t Print::print(const char str[]) 64 | { 65 | return write(str); 66 | } 67 | 68 | size_t Print::print(char c) 69 | { 70 | return write(c); 71 | } 72 | 73 | size_t Print::print(unsigned char b, int base) 74 | { 75 | return print((unsigned long) b, base); 76 | } 77 | 78 | size_t Print::print(int n, int base) 79 | { 80 | return print((long) n, base); 81 | } 82 | 83 | size_t Print::print(unsigned int n, int base) 84 | { 85 | return print((unsigned long) n, base); 86 | } 87 | 88 | size_t Print::print(long n, int base) 89 | { 90 | if (base == 0) { 91 | return write(n); 92 | } else if (base == 10) { 93 | if (n < 0) { 94 | int t = print('-'); 95 | n = -n; 96 | return printNumber(n, 10) + t; 97 | } 98 | return printNumber(n, 10); 99 | } else { 100 | return printNumber(n, base); 101 | } 102 | } 103 | 104 | size_t Print::print(unsigned long n, int base) 105 | { 106 | if (base == 0) return write(n); 107 | else return printNumber(n, base); 108 | } 109 | 110 | size_t Print::print(double n, int digits) 111 | { 112 | return printFloat(n, digits); 113 | } 114 | 115 | size_t Print::println(const __FlashStringHelper *ifsh) 116 | { 117 | size_t n = print(ifsh); 118 | n += println(); 119 | return n; 120 | } 121 | 122 | 123 | size_t Print::println(void) 124 | { 125 | return write("\r\n"); 126 | } 127 | 128 | 129 | size_t Print::println(const char c[]) 130 | { 131 | size_t n = print(c); 132 | n += println(); 133 | return n; 134 | } 135 | 136 | size_t Print::println(char c) 137 | { 138 | size_t n = print(c); 139 | n += println(); 140 | return n; 141 | } 142 | 143 | size_t Print::println(unsigned char b, int base) 144 | { 145 | size_t n = print(b, base); 146 | n += println(); 147 | return n; 148 | } 149 | 150 | size_t Print::println(int num, int base) 151 | { 152 | size_t n = print(num, base); 153 | n += println(); 154 | return n; 155 | } 156 | 157 | size_t Print::println(unsigned int num, int base) 158 | { 159 | size_t n = print(num, base); 160 | n += println(); 161 | return n; 162 | } 163 | 164 | size_t Print::println(long num, int base) 165 | { 166 | size_t n = print(num, base); 167 | n += println(); 168 | return n; 169 | } 170 | 171 | size_t Print::println(unsigned long num, int base) 172 | { 173 | size_t n = print(num, base); 174 | n += println(); 175 | return n; 176 | } 177 | 178 | size_t Print::println(double num, int digits) 179 | { 180 | size_t n = print(num, digits); 181 | n += println(); 182 | return n; 183 | } 184 | 185 | // Private Methods ///////////////////////////////////////////////////////////// 186 | 187 | size_t Print::printNumber(unsigned long n, uint8_t base) 188 | { 189 | char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte. 190 | char *str = &buf[sizeof(buf) - 1]; 191 | 192 | *str = '\0'; 193 | 194 | // prevent crash if called with base == 1 195 | if (base < 2) base = 10; 196 | 197 | do { 198 | char c = n % base; 199 | n /= base; 200 | 201 | *--str = c < 10 ? c + '0' : c + 'A' - 10; 202 | } while(n); 203 | 204 | return write(str); 205 | } 206 | 207 | size_t Print::printFloat(double number, uint8_t digits) 208 | { 209 | size_t n = 0; 210 | 211 | if (isnan(number)) return print("nan"); 212 | if (isinf(number)) return print("inf"); 213 | if (number > 4294967040.0) return print ("ovf"); // constant determined empirically 214 | if (number <-4294967040.0) return print ("ovf"); // constant determined empirically 215 | 216 | // Handle negative numbers 217 | if (number < 0.0) 218 | { 219 | n += print('-'); 220 | number = -number; 221 | } 222 | 223 | // Round correctly so that print(1.999, 2) prints as "2.00" 224 | double rounding = 0.5; 225 | for (uint8_t i=0; i 0) { 237 | n += print('.'); 238 | } 239 | 240 | // Extract digits from the remainder one at a time 241 | while (digits-- > 0) 242 | { 243 | remainder *= 10.0; 244 | unsigned int toPrint = (unsigned int)(remainder); 245 | n += print(toPrint); 246 | remainder -= toPrint; 247 | } 248 | 249 | return n; 250 | } -------------------------------------------------------------------------------- /cores/blinklib/Print.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | This is a slimed down version of the Arduino Print class for the tiles platform. 4 | Implements most cases except WStrings and Printables 5 | 6 | 7 | Original header: 8 | 9 | Print.h - Base class that provides print() and println() 10 | Copyright (c) 2008 David A. Mellis. All right reserved. 11 | 12 | This library is free software; you can redistribute it and/or 13 | modify it under the terms of the GNU Lesser General Public 14 | License as published by the Free Software Foundation; either 15 | version 2.1 of the License, or (at your option) any later version. 16 | 17 | This library is distributed in the hope that it will be useful, 18 | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 | Lesser General Public License for more details. 21 | 22 | You should have received a copy of the GNU Lesser General Public 23 | License along with this library; if not, write to the Free Software 24 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 25 | */ 26 | 27 | #ifndef Print_h 28 | #define Print_h 29 | 30 | 31 | #include // for size_t 32 | #include 33 | 34 | // This lets us use strings stored directly in flash define like `F("this is not copied to RAM")` 35 | 36 | #include 37 | 38 | // an abstract class used as a means to proide a unique pointer type 39 | // but really has no body 40 | 41 | class __FlashStringHelper; 42 | #define FPSTR(pstr_pointer) (reinterpret_cast(pstr_pointer)) 43 | #define F(string_literal) (FPSTR(PSTR(string_literal))) 44 | 45 | #define DEC 10 46 | #define HEX 16 47 | #define OCT 8 48 | #ifdef BIN // Prevent warnings if BIN is previously defined in "iotnx4.h" or similar 49 | #undef BIN 50 | #endif 51 | #define BIN 2 52 | 53 | class Print 54 | { 55 | private: 56 | size_t printNumber(unsigned long, uint8_t); 57 | size_t printFloat(double, uint8_t); 58 | public: 59 | virtual size_t write(uint8_t) = 0; 60 | size_t write(const char *str) { 61 | if (str == NULL) return 0; 62 | return write((const uint8_t *)str, strlen(str)); 63 | } 64 | virtual size_t write(const uint8_t *buffer, size_t size); 65 | size_t write(const char *buffer, size_t size) { 66 | return write((const uint8_t *)buffer, size); 67 | } 68 | 69 | // default to zero, meaning "a single write may block" 70 | // should be overriden by subclasses with buffering 71 | 72 | size_t print(const __FlashStringHelper *); 73 | size_t print(const char[]); 74 | size_t print(char); 75 | size_t print(unsigned char, int = DEC); 76 | size_t print(int, int = DEC); 77 | size_t print(unsigned int, int = DEC); 78 | size_t print(long, int = DEC); 79 | size_t print(unsigned long, int = DEC); 80 | size_t print(double, int = 2); 81 | 82 | size_t println(const __FlashStringHelper *); 83 | size_t println(const char[]); 84 | size_t println(char); 85 | size_t println(unsigned char, int = DEC); 86 | size_t println(int, int = DEC); 87 | size_t println(unsigned int, int = DEC); 88 | size_t println(long, int = DEC); 89 | size_t println(unsigned long, int = DEC); 90 | size_t println(double, int = 2); 91 | size_t println(void); 92 | 93 | virtual void flush() { /* Empty implementation for backward compatibility */ } 94 | }; 95 | 96 | 97 | /** The Printable class provides a way for new classes to allow themselves to be printed. 98 | By deriving from Printable and implementing the printTo method, it will then be possible 99 | for users to print out instances of this class by passing them into the usual 100 | Print::print and Print::println methods. 101 | */ 102 | 103 | class Printable 104 | { 105 | public: 106 | virtual size_t printTo(Print& p) const = 0; 107 | }; 108 | 109 | 110 | #endif -------------------------------------------------------------------------------- /cores/blinklib/Serial.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | A very simplified serial port built to look like Arduino's Serial class. 4 | 5 | This serial port lives on the service port on new boards. It is really intended for debugging. 6 | 7 | The port always runs at a fixed 1M baud. Dev Candy Adapter boards and cables are available to 8 | connect to a USB port and then use the Arduino IDE's serial monitor to interact with your tile. 9 | 10 | */ 11 | 12 | //#include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "sp.h" 18 | 19 | #include "Serial.h" 20 | 21 | #include "ArduinoTypes.h" 22 | 23 | 24 | // Public Methods ////////////////////////////////////////////////////////////// 25 | 26 | void ServicePortSerial::begin(void) 27 | { 28 | 29 | sp_serial_init(); 30 | 31 | } 32 | 33 | void ServicePortSerial::end() 34 | { 35 | // TODO: Is there any reason to turn off the serial port? Power? 36 | 37 | } 38 | 39 | // We only use the 1 byte hardware buffer 40 | 41 | int ServicePortSerial::available(void) { 42 | 43 | if (sp_serial_rx_ready()) { 44 | return(1); 45 | } else { 46 | return(0); 47 | } 48 | 49 | } 50 | 51 | int ServicePortSerial::read(void) 52 | { 53 | if (!sp_serial_rx_ready()) { 54 | return -1; 55 | } else { 56 | return sp_serial_rx(); 57 | } 58 | } 59 | 60 | // We don't implement flush because it would require adding a flag to remember if we ever sent. 61 | // This is because the hardware only gives us a bit that tells us when a tx completes, not if 62 | // no TX was ever started. Ardunio does this with the `_writen` flag. 63 | // If you can convince me that we really need flush, LMK and it can be added. 64 | 65 | size_t ServicePortSerial::write(uint8_t c) 66 | { 67 | 68 | sp_serial_tx(c); 69 | 70 | return(1); 71 | 72 | } 73 | 74 | // Block until all pending transmits complete 75 | 76 | void ServicePortSerial::flush(void) 77 | { 78 | sp_serial_flush(); 79 | } -------------------------------------------------------------------------------- /cores/blinklib/Serial.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | A very simplified serial port built to look like Arduino's Serial class. 4 | 5 | This serial port lives on the service port on new boards. It is really intended for debugging. 6 | 7 | The port always runs at a fixed 1M baud. Use the blink Dev Candy board to connect to a USB port 8 | and then use the Arduino IDE's serial monitor to interact with your tile. 9 | 10 | */ 11 | 12 | 13 | #ifndef Serial_h 14 | 15 | #define Serial_h 16 | 17 | #include "Print.h" 18 | 19 | #define DEF_SERVICE_PORT_BAUDRATE 1000000 20 | 21 | class ServicePortSerial : public Print 22 | { 23 | 24 | public: 25 | 26 | //inline ServicePortSerialSerial(void); 27 | void begin(void); 28 | void end(); 29 | 30 | virtual int available(void); 31 | 32 | // Input buffer is only 1 byte so if an interrupts happens while data is streaming, you will loose any incoming data. 33 | // Best to limit yourself interactions with plenty of time (or an ACK) between each incoming byte. 34 | 35 | virtual int read(void); // Read a byte - returns byte read or -1 if no byte ready. 36 | 37 | virtual size_t write(uint8_t); 38 | void flush(void); // Block until all pending transmits complete 39 | 40 | using Print::write; // pull in write(str) and write(buf, size) from Print 41 | 42 | 43 | }; 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /cores/blinklib/Timer.cpp: -------------------------------------------------------------------------------- 1 | #include // Get ULONG_MAX for NEVER 2 | 3 | #include "blinklib.h" 4 | // Note we directly access millis() here, which is really bad style. 5 | // The timer should capture millis() in a closure, but no good way to 6 | // do that in C++ that is not verbose and inefficient, so here we are. 7 | 8 | #define NEVER (ULONG_MAX) 9 | 10 | // All Timers come into this world pre-expired, so their expireTime is 0 11 | // Here we leave the constructor empty and depend in the BBS section clearing 12 | // to set it to 0 (the constructor mechanism uses lots of flash). 13 | 14 | bool Timer::isExpired() { 15 | return millis() > m_expireTime; 16 | } 17 | 18 | void Timer::set( uint32_t ms ) { 19 | m_expireTime= millis()+ms; 20 | } 21 | 22 | uint32_t Timer::getRemaining() { 23 | 24 | uint32_t timeRemaining; 25 | 26 | if( millis() >= m_expireTime) { 27 | 28 | timeRemaining = 0; 29 | 30 | } else { 31 | 32 | timeRemaining = m_expireTime - millis(); 33 | 34 | } 35 | 36 | return timeRemaining; 37 | 38 | } 39 | 40 | void Timer::add( uint16_t ms ) { 41 | 42 | // Check to avoid overflow 43 | 44 | uint32_t timeLeft = NEVER - m_expireTime; 45 | 46 | if (ms > timeLeft ) { 47 | 48 | m_expireTime = NEVER; 49 | 50 | } else { 51 | 52 | m_expireTime+= ms; 53 | 54 | } 55 | } 56 | 57 | void Timer::never(void) { 58 | m_expireTime=NEVER; 59 | } 60 | 61 | -------------------------------------------------------------------------------- /cores/blinklib/main.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Here are our magic shared memory links to the BlinkBIOS running up in the bootloader area. 3 | // These special sections are defined in a special linker script to make sure that the addresses 4 | // are the same on both the foreground (this blinklib program) and the background (the BlinkBIOS project compiled to a HEX file) 5 | 6 | #include "shared/blinkbios_shared_button.h" 7 | #include "shared/blinkbios_shared_millis.h" 8 | #include "shared/blinkbios_shared_pixel.h" 9 | #include "shared/blinkbios_shared_irdata.h" 10 | 11 | #include "blinklib.h" 12 | 13 | #include "run.h" 14 | 15 | // Here are the actual allocations for the shared memory blocks 16 | 17 | // We put each in its own section so that the separately compiled blinkos will be able to find them. 18 | 19 | // Note that without the `used` attribute, these blocks get tossed even though they are marked as `KEEP` in the linker script 20 | 21 | blinkbios_pixelblock_t __attribute__ ((section (".ipcram1") , used )) blinkbios_pixel_block; 22 | blinkbios_millis_block_t __attribute__ ((section (".ipcram2") , used )) blinkbios_millis_block; 23 | blinkbios_button_block_t __attribute__ ((section (".ipcram3") , used )) blinkbios_button_block; 24 | blinkbios_irdata_block_t __attribute__ ((section (".ipcram4") , used )) blinkbios_irdata_block; 25 | 26 | // Here is our entry point. We are called by the BlinkBIOS after everything is set up and ready 27 | // Note that this is not a normal startup, we are staring right from flash address 0x000 with no 28 | // vector table at all. We don't need one because all vectors are pointing to the BlinkBIOS 29 | // running up in the bootloader area. 30 | 31 | // We will never return, so don't need any of the extra formality, just give me the straight up code 32 | 33 | #include 34 | 35 | extern "C" void mainx(void) __attribute__ ((used)) __attribute__ ((noreturn)); 36 | 37 | extern "C" void mainx(void) { 38 | 39 | run(); 40 | 41 | __builtin_unreachable(); 42 | 43 | // Don't fall off the edge of the earth here! 44 | // Make sure we stop above! 45 | } 46 | -------------------------------------------------------------------------------- /cores/blinklib/run.h: -------------------------------------------------------------------------------- 1 | 2 | // Link from mainx() into blinklib.cpp 3 | // Called to start the sketch. 4 | 5 | void __attribute__((noreturn)) run(void); -------------------------------------------------------------------------------- /cores/blinklib/shared/blinkbios_shared_button.h: -------------------------------------------------------------------------------- 1 | /* 2 | * blinkbios_pixel_block.h 3 | * 4 | * Defines the shared memory block used to check for button presses 5 | * 6 | */ 7 | 8 | #ifndef BLINKBIOS_BUTTON_BLOCK_H_ 9 | #define BLINKBIOS_BUTTON_BLOCK_H_ 10 | 11 | // #define USER_VOLATILE or BIOS_VOLATILE based on the presence of #define BIOS_VOLATILE_FLAG 12 | #include "blinkbios_shared_volatile.h" 13 | 14 | #include 15 | 16 | // I know this is ugly, but keeping them in a single byte lets us pass them by value 17 | // and also lets us OR them together. Efficiency in the updater trumps since it 18 | // runs every millisecond. 19 | 20 | // TODO: Maybe more RAM but less flash to have these as individual bytes? 21 | 22 | #define BUTTON_BITFLAG_PRESSED 0b00000001 23 | #define BUTTON_BITFLAG_LONGPRESSED 0b00000010 24 | #define BUTTON_BITFLAG_RELEASED 0b00000100 25 | #define BUTTON_BITFLAG_SINGLECLICKED 0b00001000 26 | #define BUTTON_BITFLAG_DOUBLECLICKED 0b00010000 27 | #define BUTTON_BITFLAG_MULITCLICKED 0b00100000 28 | 29 | #define BUTTON_BITFLAG_3SECPRESSED 0b01000000 30 | #define BUTTON_BITFLAG_6SECPRESSED 0b10000000 31 | 32 | struct blinkbios_button_block_t { 33 | 34 | USER_VOLATILE uint8_t down; // 1 if button is currently down (debounced) 35 | 36 | BOTH_VOLATILE uint8_t bitflags; 37 | 38 | USER_VOLATILE uint8_t clickcount; // Number of clicks on most recent multiclick 39 | 40 | BOTH_VOLATILE uint8_t wokeFlag; // Set to 0 upon initial start up or waking from sleep 41 | 42 | // The variables below are used to track the intermediate button state 43 | // and probably not interesting to user programs 44 | 45 | uint8_t buttonDebounceCountdown; // How long until we are done bouncing. Only touched in the callback 46 | // Set to BUTTON_DEBOUNCE_MS every time we see a change, then we ignore everything 47 | // until it gets to 0 again 48 | 49 | uint16_t clickWindowCountdown; // How long until we close the current click window. 0=done 50 | 51 | uint8_t clickPendingcount; // How many clicks so far int he current click window 52 | 53 | uint8_t longpressRegisteredFlag; // Did we register a long press since the button went down? 54 | // Avoids multiple long press events from the same down event 55 | // We could keep an independent longpressCountup, but that would be a 16 bit so heavy to increment and compare. 56 | 57 | uint16_t pressCountup; // Start counting up when the button goes down to detect long presses. Has to be 16 bit because long presses are >255 centiseconds. 58 | 59 | // For future use? 60 | uint8_t slack[4]; 61 | 62 | 63 | }; 64 | 65 | // Everything in here is volatile to the user code 66 | 67 | extern blinkbios_button_block_t blinkbios_button_block; 68 | 69 | #endif /* BLINKBIOS_BUTTON_BLOCK_H_ */ -------------------------------------------------------------------------------- /cores/blinklib/shared/blinkbios_shared_functions.h: -------------------------------------------------------------------------------- 1 | /* 2 | * blinkbios_shared_functions.h 3 | * 4 | * Defines the entry points into the BLINKBIOS called functions 5 | * 6 | */ 7 | 8 | // Note: Aesthetically it might seem better to put these function declarations with their functional groups, but ultimately I decided to 9 | // keep them all here in one place to avoid vector collisions. It is not a decision without downside though since a client who, say, 10 | // only wants the IR send funtion gets polluted with the others as well. :/ 11 | 12 | // The VECTOR definitions are used on the BIOS side to hook the correct incoming vector. 13 | // The function definitions are used on the caller side to make the actual call to the vector. 14 | // The vector number and the jmp address must be manually matched. 15 | 16 | // The actual vector number is not important as long as it is not used for an actual ISR. We really just use the vector pattern so the 17 | // caller has a well known address to jmp to and vectors are always at a well known address. 18 | 19 | // The `jmp`s just work because the caller will set up the args in the right registers and then make the jmp to the 20 | // interrupt vector. Once there, the vector will directly call the target function with all the args still in place, 21 | // then the target will return back to the original caller. Cool right? The optimizer will even put the target function at 22 | // the vector jump address if it has no other callers, saving a jmp. 23 | 24 | #ifndef BLINKBIOS_SHARED_FUCNTIONS_H_ 25 | #define BLINKBIOS_SHARED_FUCNTIONS_H_ 26 | 27 | // Send a user data packet 28 | // See what we did here - we do a naked jump into vector_4, which is a jump to the `uint8_t ir_send_userdata( uint8_t face, const uint8_t *data , uint8_t len )` function 29 | // it all works out because the params happened to be in the same registers because of the AVR C calling convention. 30 | // When compiling the BIOS with LTO, it even puts the send packet function right at the target of the vector. 31 | 32 | // We use unused inetrrupt vectors to link between the user and BIOS code since they are at a known place. 33 | // The links are defined as symbols like `boot_vectorX` where X is the number of the unused vector we are taking. 34 | // In the BIOS project, these appear in the vector table in `startup.S`. 35 | // IN the user mode projects, these appear in the linkscript and are hard coded to the correct addressed (based at the bootloader vtable at 0x3800). 36 | 37 | // boot_vector4 is defined in the linkerscript and points to the boot loader's interrupt vector 4 at address 0x3810 38 | // This is just a prototype so gcc knows what args to pass. The linker will resolve it to a jump to the address. 39 | 40 | #define BLINKBIOS_IRDATA_SEND_PACKET_VECTOR boot_vector4 // This lands at base + 4 bytes per vector * 4th vector (init is at 0) = 0x10 41 | 42 | extern "C" uint8_t BLINKBIOS_IRDATA_SEND_PACKET_VECTOR( uint8_t face, const uint8_t *data , uint8_t len ) __attribute__((used)) __attribute__((noinline)); 43 | 44 | // Translate and copy the RGB values in the pixel buffer to raw PWM values in the 45 | // raw pixel buffer. Waits for next vertical blanking interval to avoid 46 | // display of partial update. 47 | 48 | #define BLINKBIOS_DISPLAY_PIXEL_BUFFER_VECTOR boot_vector8 49 | 50 | extern "C" void BLINKBIOS_DISPLAY_PIXEL_BUFFER_VECTOR() __attribute__((used)) __attribute__((noinline)); 51 | 52 | 53 | 54 | #define BLINKBIOS_BOOTLOADER_SEED_VECTOR boot_vector9 55 | 56 | extern "C" void BLINKBIOS_BOOTLOADER_SEED_VECTOR() __attribute__((used)) __attribute__((noinline)); 57 | 58 | 59 | // Push back the inactivity sleep timer 60 | // Can be called with interrupts off, so you can adjust the 61 | // blinkbios_millis_block.millis and then call BLINKBIOS_POSTPONE_SLEEP_VECTOR 62 | // to reset the sleep_time to match the new timebase 63 | // Leaves with interrupts ON 64 | 65 | #define BLINKBIOS_POSTPONE_SLEEP_VECTOR boot_vector10 66 | 67 | extern "C" void BLINKBIOS_POSTPONE_SLEEP_VECTOR() __attribute__((used)) __attribute__((noinline)); 68 | 69 | 70 | #define BLINKBIOS_SLEEP_NOW_VECTOR boot_vector12 71 | 72 | extern "C" void BLINKBIOS_SLEEP_NOW_VECTOR() __attribute__((used)) __attribute__((noinline)); 73 | 74 | // Fill the flash page buffer using the boot_page_fill() function, 75 | // then call here. Will write the page to flash, wait for it to complete, 76 | // re-enable the rww part of flash, then return - so you can call this from 77 | // the non-bootloader part of memory 78 | 79 | #define BLINKBIOS_WRITE_FLASH_PAGE_VECTOR boot_vector13 80 | 81 | extern "C" void BLINKBIOS_WRITE_FLASH_PAGE_VECTOR(uint8_t page) __attribute__((used)) __attribute__((noinline)); 82 | 83 | 84 | // Returns the version of the blinksbios present 85 | 86 | #define BLINKBIOS_VERSION_VECTOR boot_vector14 87 | 88 | extern "C" uint8_t BLINKBIOS_VERSION_VECTOR() __attribute__((used)) __attribute__((noinline)); 89 | 90 | 91 | // Error mode. Blinks red until button pressed, then soft reset 92 | 93 | #define BLINKBIOS_ABEND_VECTOR boot_vector15 94 | 95 | extern "C" void BLINKBIOS_ABEND_VECTOR( uint8_t blinkCount ) __attribute__((used)) __attribute__((noinline)) __attribute__((noreturn)); 96 | 97 | #endif /* BLINKBIOS_SHARED_FUCNTIONS_H_ */ -------------------------------------------------------------------------------- /cores/blinklib/shared/blinkbios_shared_irdata.h: -------------------------------------------------------------------------------- 1 | /* 2 | * blinkbios_pixel_block.h 3 | * 4 | * Defines the shared memory block used to check for button presses 5 | * 6 | */ 7 | 8 | #ifndef BLINKBIOS_IRDATA_BLOCK_H_ 9 | #define BLINKBIOS_IRDATA_BLOCK_H_ 10 | 11 | // #define USER_VOLATILE or BIOS_VOLATILE based on the presence of #define BIOS_VOLATILE_FLAG 12 | #include "blinkbios_shared_volatile.h" 13 | 14 | #include 15 | 16 | #define IR_FACE_COUNT 6 17 | #define IR_FACE_BITMASK 0b00111111 // Mask for the 6 faces. Fails hard when we start making nonagon tiles. 18 | 19 | // Must be big enough to hold the biggest packet, which internally is PUSH packet. 20 | #define IR_RX_PACKET_SIZE 40 21 | 22 | // State for each receiving IR LED 23 | 24 | 25 | // User programs should only pay attention to messages with the header byte 26 | // they should silently consume any messages with other header bytes. 27 | 28 | #define IR_USER_DATA_HEADER_BYTE 0b00110111 29 | 30 | struct ir_rx_state_t { 31 | 32 | BOTH_VOLATILE uint8_t packetBufferReady; // 1 if we got the trailing sync byte. Foreground reader will set this back to 0 to enable next read. 33 | 34 | BOTH_VOLATILE uint8_t txInProgressFlag; // Are we currently transmitting? If so, then ignore any incoming SYNC. 35 | 36 | USER_VOLATILE uint8_t packetBufferLen; // How many bytes currently in the packet buffer? Does not include checksum when bufferReady is set 37 | 38 | 39 | USER_VOLATILE uint8_t packetBuffer[ IR_RX_PACKET_SIZE+1 ]; // Assemble incoming packet here. +1 to hold the type byte. Type byte comes first, but shoul;d be ignored since the BIOS consumes anything with a type besides USERDATA 40 | // First byte is header, which user code must check for USERDATA 41 | 42 | // These internal variables not interesting to user code. 43 | // They are only updated in ISR, so don't need to be volatile. 44 | 45 | uint8_t windowsSinceLastTrigger; // How long since we last saw a trigger on this IR LED? 46 | 47 | // We add new samples to the bottom and shift up. 48 | // The we look at the pattern to detect data bits 49 | // This is better than using a counter because with a counter we would need 50 | // to check for overflow before incrementing. With a shift register like this, 51 | // 1's just fall off the top automatically and We can keep shifting 0's forever. 52 | 53 | uint8_t byteBuffer; // Buffer for RX byte in progress. Data bits shift up until full byte received. 54 | // We prime with a '1' in the bottom bit when we get a valid start. 55 | // This way we can test for 0 to see if currently receiving a byte, and 56 | // we can also test for '1' in top position to see if full byte received. 57 | 58 | 59 | // This struct should be even power of 2 in length for more efficient array indexing. 60 | 61 | // For future use? 62 | uint8_t slack[4]; 63 | 64 | 65 | }; 66 | 67 | struct blinkbios_irdata_block_t { 68 | 69 | ir_rx_state_t ir_rx_states[ IR_FACE_COUNT ]; 70 | 71 | uint8_t download_in_progress_flag; // Set if a download is in progress so subsequent SEED packets will be ignored 72 | 73 | // For future use? 74 | uint8_t slack[4]; 75 | 76 | 77 | }; 78 | 79 | extern blinkbios_irdata_block_t blinkbios_irdata_block; 80 | 81 | // You can use this function to see if there is an RX in progress on a face 82 | // Don't transmit if there is an RX in progress or you'll make a collision 83 | 84 | inline uint8_t blinkbios_is_rx_in_progress( uint8_t face ) { 85 | 86 | // This uses the fact that anytime we are actively receiving a byte, the byte buffer will 87 | // be nonzero. Even if we are getting an all-0 byte, the top bit will be marching up. 88 | // This is handy, but it does allow a collision during the leading sync. See below. 89 | 90 | return blinkbios_irdata_block.ir_rx_states[face].byteBuffer; 91 | 92 | } 93 | 94 | 95 | #endif /* BLINKBIOS_IRDATA_BLOCK_H_ */ -------------------------------------------------------------------------------- /cores/blinklib/shared/blinkbios_shared_millis.h: -------------------------------------------------------------------------------- 1 | /* 2 | * blinkbios_millis_block.h 3 | * 4 | * Defines the shared memory block used to keep the millisecond counter 5 | * 6 | */ 7 | 8 | #ifndef BLINKBIOS_MILLIS_BLOCK_H_ 9 | #define BLINKBIOS_MILLIS_BLOCK_H_ 10 | 11 | // C++ implementations should define these macros only when __STDC_LIMIT_MACROS is defined before is included 12 | 13 | #define __STDC_CONSTANT_MACROS 14 | #define __STDC_LIMIT_MACROS 15 | 16 | //C++ implementations should define these macros only when __STDC_LIMIT_MACROS is defined before is included. 17 | // Gets us the UINT*_MAX macros 18 | #define __STDC_LIMIT_MACROS 19 | 20 | #include 21 | 22 | // #define USER_VOLATILE or BIOS_VOLATILE based on the presence of #define BIOS_VOLATILE_FLAG 23 | #include "blinkbios_shared_volatile.h" 24 | 25 | typedef uint32_t millis_t; 26 | 27 | #define MILLIS_MAX ( UINT32_MAX ) // This is a hack because it seems our compiled does not have UINT32_MAX correctly defined. :/ 28 | 29 | struct blinkbios_millis_block_t { 30 | 31 | USER_VOLATILE millis_t millis; 32 | USER_VOLATILE uint8_t step_8us; // Carry over of sub-millis since our clock does not go evenly into 1ms. This is the number of 8us steps past the value in millis. Never gets above 125. 33 | 34 | USER_VOLATILE millis_t sleep_time; // When millis>sleep_time, then we go to sleep 35 | 36 | // For future use? 37 | uint8_t slack[4]; 38 | }; 39 | 40 | extern blinkbios_millis_block_t blinkbios_millis_block; 41 | 42 | 43 | #define MILLIS_NEVER ( MILLIS_MAX ) // A time that will forever be in the future 44 | 45 | 46 | #endif /* BLINKBIOS_MILLIS_BLOCK_H_ */ -------------------------------------------------------------------------------- /cores/blinklib/shared/blinkbios_shared_pixel.h: -------------------------------------------------------------------------------- 1 | /* 2 | * blinkbios_pixel_block.h 3 | * 4 | * Defines the shared memory block used to set the color of the pixels 5 | * and to determine best time to update the values 6 | * 7 | */ 8 | 9 | #ifndef BLINKBIOS_PIXEL_BLOCK_H_ 10 | #define BLINKBIOS_PIXEL_BLOCK_H_ 11 | 12 | // #define USER_VOLATILE or BIOS_VOLATILE based on the presence of #define BIOS_VOLATILE_FLAG 13 | #include "blinkbios_shared_volatile.h" 14 | 15 | /** Display interface ***/ 16 | 17 | #define PIXEL_COUNT 6 18 | 19 | // Here are the raw compare register values for each pixel 20 | // These are precomputed from brightness values because we read them often from inside an ISR 21 | // Note that for red & green, 255 corresponds to OFF and 0 is full on 22 | 23 | struct rawpixel_t { 24 | uint8_t rawValueR; 25 | uint8_t rawValueG; 26 | uint8_t rawValueB; 27 | uint8_t paddng; // Adding this padding save about 10 code bytes since x4 (double-doubling) is faster than adding 3. 28 | 29 | rawpixel_t( uint8_t in_raw_r , uint8_t in_raw_g , uint8_t in_raw_b ) { 30 | rawValueR = in_raw_r; 31 | rawValueG = in_raw_g; 32 | rawValueB = in_raw_b; 33 | 34 | } 35 | 36 | rawpixel_t() {}; 37 | 38 | }; 39 | 40 | 41 | const rawpixel_t RAW_PIXEL_OFF( 0xff , 0xff, 0xff ); 42 | 43 | // pixel_color_t is a higher level view RGB encoded of a pixel 44 | 45 | // Each pixel has 32 brightness levels for each of the three colors (red,green,blue) 46 | // These brightness levels are normalized to be visually linear with 0=off and 31=max brightness 47 | 48 | // Note use of anonymous union members to let us switch between bitfield and int 49 | // https://stackoverflow.com/questions/2468708/converting-bit-field-to-int 50 | 51 | union pixelColor_t { 52 | 53 | struct { 54 | uint8_t reserved:1; 55 | uint8_t r:5; 56 | uint8_t g:5; 57 | uint8_t b:5; 58 | }; 59 | 60 | uint16_t as_uint16; 61 | 62 | pixelColor_t(); 63 | pixelColor_t(uint8_t r_in , uint8_t g_in, uint8_t b_in ); 64 | pixelColor_t(uint8_t r_in , uint8_t g_in, uint8_t b_in , uint8_t reserverd_in ); 65 | 66 | }; 67 | 68 | inline pixelColor_t::pixelColor_t(uint8_t r_in , uint8_t g_in, uint8_t b_in ) { 69 | 70 | r=r_in; 71 | g=g_in; 72 | b=b_in; 73 | 74 | } 75 | 76 | inline pixelColor_t::pixelColor_t(uint8_t r_in , uint8_t g_in, uint8_t b_in , uint8_t reserverd_in ) { 77 | 78 | r=r_in; 79 | g=g_in; 80 | b=b_in; 81 | reserved = reserverd_in; 82 | 83 | } 84 | 85 | /* 86 | 87 | template pixelColor_t preset_pixelcolor_t { 88 | { 89 | pixelColor_t p = pixelColor_t( r , g , b ); 90 | 91 | 92 | }; 93 | 94 | */ 95 | 96 | // Maximum value you can assign to one of the primaries in a pixelColor_t 97 | #define PIXELCOLOR_PRIMARY_FULL 31 98 | #define PIXELCOLOR_PRIMARY_HALF 15 99 | 100 | // So this mess below is my way of emulating constexpr in C++ <11 101 | // These defines will expand and eval at compile time down to a single uint16_t load 102 | // if instead we tried using a `const pixelColor_r`, then it would blow up into 103 | // a constructor call at runtime. Yuck. 104 | 105 | #define PIXEL_COLOR_FULL_GREEN pixelColor_t( 0 , PIXELCOLOR_PRIMARY_FULL , 0 ) 106 | #define PIXEL_COLOR_HALF_GREEN pixelColor_t( 0 , PIXELCOLOR_PRIMARY_HALF , 0 ) 107 | 108 | #define PIXEL_COLOR_FULL_RED pixelColor_t( PIXELCOLOR_PRIMARY_FULL , 0 , 0 ) 109 | #define PIXEL_COLOR_HALF_RED pixelColor_t( PIXELCOLOR_PRIMARY_HALF , 0 , 0 ) 110 | 111 | #define PIXEL_COLOR_FULL_BLUE pixelColor_t( 0 , 0 , PIXELCOLOR_PRIMARY_FULL ) 112 | 113 | #define PIXEL_COLOR_OFF pixelColor_t() 114 | 115 | inline pixelColor_t::pixelColor_t() { 116 | 117 | // Faster than setting the individual elements? 118 | // We don't need to do this because in bss this will get cleared to 0 anyway. 119 | // as_uint16 = 0; 120 | 121 | } 122 | 123 | // Oh how I hate these defines, but we are not allowed to have nice things like 124 | // scoped enums until C++11, so no better way to makes these fit into uint8_t 125 | 126 | #define BLINKBIOS_START_STATE_POWER_UP 0 127 | #define BLINKBIOS_START_STATE_WE_ARE_ROOT 1 128 | #define BLINKBIOS_START_STATE_DOWNLOAD_SUCCESS 2 129 | 130 | // We need these struct gymnastics because C fixed array typedefs do not work 131 | // as you (I?) think they would... 132 | // https://stackoverflow.com/questions/4523497/typedef-fixed-length-array 133 | 134 | struct blinkbios_pixelblock_t { 135 | 136 | // RGB pixel buffer 137 | // Call displayPixelBuffer() to decode and copy this into the raw pixel buffer 138 | // so it will appear on the LEDs 139 | 140 | BIOS_VOLATILE pixelColor_t pixelBuffer[PIXEL_COUNT]; 141 | 142 | // This is cleared when we are done displaying the current buffer values and about to reset and start again 143 | // Once this is cleared, you have one pixel interrupt period to get your new data into the pixel buffer 144 | // before the next refresh cycle starts. 145 | 146 | // We picked to clear this rather than set to 1 because in the ISR is is faster to set to 0 since R1 is always loaded with 0 147 | 148 | BOTH_VOLATILE uint8_t vertical_blanking_interval; 149 | 150 | // Below is some global state that is probably not interesting to user code 151 | 152 | rawpixel_t rawpixels[PIXEL_COUNT]; 153 | 154 | uint8_t currentPixelIndex; // Which pixel are we currently lighting? Pixels are multiplexed and only refreshed one at a time in sequence. 155 | uint8_t phase; // Phase up updating the current pixel. There are 5 phases that include lighting each color, charging the charge pump, and resting the charge pump. 156 | 157 | 158 | // Here we keep the value of TCNT0 that was captured at the last watchdog timer interrupt 159 | // We put this here because the pixel code enables and sets up Timer0, and really not other good place for it. 160 | // User code is responsible for enabling the WDT interrupt and then checking this value to see 161 | // when it gets set asynchronously by the bios WDT ISR. 162 | 163 | volatile uint8_t capturedEntropy; 164 | 165 | // This is 1 if we just successfully send a download out 166 | // (not volatile, never changes from client program perspective) 167 | 168 | BIOS_VOLATILE uint8_t start_state; 169 | 170 | // For future use? 171 | uint8_t slack[8]; 172 | 173 | }; 174 | 175 | extern blinkbios_pixelblock_t blinkbios_pixel_block; // Currently being displayed. You can have direct access to this to save memory, 176 | // but use the vertical retrace to avoid visual tearing on updates 177 | 178 | #endif /* BLINKBIOS_PIXEL_BLOCK_H_ */ -------------------------------------------------------------------------------- /cores/blinklib/shared/blinkbios_shared_volatile.h: -------------------------------------------------------------------------------- 1 | /* 2 | * blinkbios_shared_voltaile.h 3 | * 4 | * This is a workaround to letting the BIOS code and user code have different `volatile` views of the 5 | * shared data structures. While we need some of these shared variables to be seen as volatile to the user code 6 | * since they can be changed by the BIOS code in the background, the BIOS code can never be interrupted by the user code 7 | * so it is wasteful to have it see them as volatile also. All the unneeded reloads are not only slow, but we really need 8 | * to save flash. 9 | * 10 | * To make this work, the BIOS code always `#define`s `BIOS_VOLATILE_FLAG` before including any of the shared files. 11 | * 12 | */ 13 | 14 | 15 | #ifndef BLINKBIOS_SHAED_VOLATILE__H_ 16 | 17 | #define BLINKBIOS_SHAED_VOLATILE__H_ 18 | 19 | #ifdef BIOS_VOLATILE_FLAG 20 | 21 | // BIOS code sees this 22 | 23 | #define BIOS_VOLATILE volatile 24 | #define USER_VOLATILE 25 | #define BOTH_VOLATILE volatile 26 | 27 | #else 28 | 29 | // User code sees this 30 | 31 | #define BIOS_VOLATILE 32 | #define USER_VOLATILE volatile 33 | #define BOTH_VOLATILE volatile 34 | 35 | #endif 36 | 37 | 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /cores/blinklib/shared/readme.MD: -------------------------------------------------------------------------------- 1 | Do not manually change these files! 2 | 3 | They come from the `blinkbios` project... 4 | 5 | https://github.com/Move38/Move38-BlinkBIOS 6 | 7 | ...and must travel as a coherent set. 8 | 9 | `BlinkBIOS.hex` contains the compiled image of the BlinkBIOS code. It is loaded in upper flash and takes care of lots of common hardware tasks so that individual games do not need duplicated code. 10 | 11 | We program this file every time download a sketch. We also set the `BOOTRST` fuse so that the chip will jump to the bootload section rather than address 0x000 on RESET. Both of these happen in the `AVRDUDE` the recipes in `platform.txt`. 12 | 13 | To be able to successfully talk to the BIOS code, the blink user code must be compiled against the matching header files. 14 | -------------------------------------------------------------------------------- /cores/blinklib/sp.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Access the service port 3 | * 4 | * The service port has a high speed (1Mbps) bi-directional serial connection plus an Aux pin that can be used 5 | * as either digitalIO or an analog in. 6 | * 7 | * Mostly useful for debugging, but maybe other stuff to? :) 8 | * 9 | */ 10 | 11 | 12 | #include "sp.h" 13 | 14 | #include 15 | 16 | // Serial port hardware on service port 17 | 18 | #define SP_SERIAL_CTRL_REG UCSR0A 19 | #define SP_SERIAL_DATA_REG UDR0 20 | #define SP_SERIAL_READY_BIT RXC0 21 | 22 | // Bit manipulation macros 23 | #define SBI(x,b) (x|= (1<linker 23 | 24 | 25 | 26 | * Created: 10/27/2018 4:05:41 PM 27 | * Author: josh 28 | */ 29 | 30 | 31 | /* 32 | 33 | There is nothing here! NO VECTORS here! No __zero_reg! We just jump stright into the code! 34 | 35 | This saves a lot of flash becuase each game can start litterally at address 0x000 and hit the 36 | ground running with no extra crap at the begining. 37 | 38 | The vectors are up in the bootloader area. Code compiled against this blinklib API 39 | is depenent on that BlinkBIOS code running at reset and setting everythign up for us 40 | inclduing the interrupts. 41 | 42 | Note that we do need to init the .data and .bss variables to thier initial values, but that 43 | is taken care of by library code that will link in here automatically. 44 | 45 | */ 46 | 47 | // There does not seem to be any good way to avoid this jmp since 48 | // the compiler likes to put the contructors and jump trampolines at the bottom of flash, 49 | // which ended up being 0x0000 when we get rid of all the vectors! 50 | 51 | 52 | .section .vectors,"ax",@progbits 53 | .global __vectors 54 | .func __vectors 55 | __vectors: 56 | jmp __init 57 | .endfunc 58 | 59 | 60 | .section .init0,"ax",@progbits 61 | .func __init 62 | __init: 63 | 64 | .section .init2,"ax",@progbits 65 | 66 | .section .init9,"ax",@progbits 67 | 68 | // Note that we do not need to clear `r1` or set up the stack here 69 | // becuase the BlinkBIOS has already done that by the time we get started. 70 | 71 | jmp mainx 72 | 73 | .endfunc 74 | -------------------------------------------------------------------------------- /libraries/Examples01/dummy.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Atmel Corp./Thibaut VIARD. All right reserved. 3 | 4 | This library is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU Lesser General Public 6 | License as published by the Free Software Foundation; either 7 | version 2.1 of the License, or (at your option) any later version. 8 | 9 | This library is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 | See the GNU Lesser General Public License for more details. 13 | 14 | You should have received a copy of the GNU Lesser General Public 15 | License along with this library; if not, write to the Free Software 16 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | */ 18 | 19 | /* 20 | * Workaround dummy file to obtain the examples present in the IDE menu File->Examples 21 | */ 22 | -------------------------------------------------------------------------------- /libraries/Examples01/examples/A-BareMinimum/A-BareMinimum.ino: -------------------------------------------------------------------------------- 1 | void setup() { 2 | // put your start up code here, it will run 3 | // every time this blink wakes up 4 | 5 | } 6 | 7 | void loop() { 8 | // put your main code here, to run repeatedly 9 | // every time a new frame of pixels is displayed 10 | // on the front of this blink 11 | 12 | } 13 | -------------------------------------------------------------------------------- /libraries/Examples01/examples/B-ButtonPress/B-ButtonPress.ino: -------------------------------------------------------------------------------- 1 | void setup() { 2 | 3 | // No setup needed for this simple example! 4 | 5 | } 6 | 7 | void loop() { 8 | 9 | if (buttonDown()) { 10 | 11 | setColor( RED ); 12 | 13 | } else { 14 | 15 | setColor( GREEN ); 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /libraries/Examples01/examples/C-ButtonCycleColors/C-ButtonCycleColors.ino: -------------------------------------------------------------------------------- 1 | void setup() { 2 | 3 | // No setup needed for this simple example! 4 | 5 | } 6 | 7 | byte counter=0; 8 | 9 | void loop() { 10 | 11 | if (buttonPressed()) { 12 | 13 | counter = counter + 1; 14 | 15 | if ( counter >= 3 ) { 16 | 17 | counter = 0; 18 | 19 | } 20 | } 21 | 22 | if (counter==0) { 23 | setColor(RED); 24 | } else if (counter==1) { 25 | setColor(GREEN); 26 | } else { // if (counter==2) 27 | setColor(BLUE); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /libraries/Examples01/examples/D-TimerFlash/D-TimerFlash.ino: -------------------------------------------------------------------------------- 1 | void setup() { 2 | 3 | // No setup needed for this simple example! 4 | 5 | } 6 | 7 | Timer nextFlash; // Timers are initialized as already being expired, so we will flash the first time loop() called. 8 | 9 | void loop() { 10 | 11 | if (nextFlash.isExpired()) { 12 | 13 | setColor( RED ); 14 | 15 | nextFlash.set(200); // Flash again in 200 millseconds 16 | 17 | } else { 18 | 19 | setColor( OFF ); 20 | 21 | } 22 | 23 | // Any color set in loop() is guaranteed to show up on the tile for at least one frame, 24 | // which is about 1/60th of a second. It will be a fast flash, but visible. 25 | 26 | } 27 | -------------------------------------------------------------------------------- /libraries/Examples01/examples/E-TimerBlink/E-TimerBlink.ino: -------------------------------------------------------------------------------- 1 | void setup() { 2 | 3 | // No setup needed for this simple example! 4 | 5 | } 6 | 7 | bool onFlag = false; 8 | 9 | Timer nextChange; 10 | 11 | 12 | void loop() { 13 | 14 | if (nextChange.isExpired()) { 15 | 16 | if (onFlag) { 17 | 18 | setColor( OFF ); 19 | onFlag = false; 20 | 21 | } else { 22 | 23 | setColor(BLUE); 24 | onFlag = true; 25 | 26 | } 27 | 28 | nextChange.set(500); // Toggle every 500 milliseconds 29 | 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /libraries/Examples01/examples/F-ColorWheel/F-ColorWheel.ino: -------------------------------------------------------------------------------- 1 | // Spin around in goovy HSB color space 2 | // HSB stands for Hue, Saturation, and Brightness 3 | // https://en.wikipedia.org/wiki/HSL_and_HSV 4 | 5 | void setup() { 6 | // No setup needed for this simple example! 7 | } 8 | 9 | byte hue=0; 10 | 11 | Timer nextStep; 12 | 13 | void loop() { 14 | 15 | if (nextStep.isExpired()) { 16 | 17 | // Spin the hue while keeping color saturation and brightness at max 18 | setColor( makeColorHSB( hue , 255 , 255 ) ); 19 | 20 | // Becuase we are using an 8-bit byte for the `hue` variable, 21 | // this will automatically roll over from 255 back down to 0 22 | // (255 is 11111111 in binary, and 11111111 + 00000001 = 00000000) 23 | hue++; 24 | 25 | nextStep.set(10); // Step to (slightly) different color 100 times per second - whole cycle will take 255 steps *10ms = ~2.5 seconds. 26 | 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /libraries/Examples01/examples/G-StartState/G-StartState.ino: -------------------------------------------------------------------------------- 1 | // Show how the current game was loaded 2 | // BLUE - We are the root of a download seed 3 | // GREEN - We downloaded the game from someone else (not root) 4 | // RED - Anything else (battery changed, failed download, etc) 5 | 6 | void setup() { 7 | 8 | // No setup needed for this simple example! 9 | 10 | } 11 | 12 | void loop() { 13 | 14 | 15 | Color color; 16 | 17 | switch ( startState() ) { 18 | 19 | case START_STATE_WE_ARE_ROOT: 20 | color = BLUE; 21 | break; 22 | 23 | case START_STATE_DOWNLOAD_SUCCESS: 24 | color = GREEN; 25 | break; 26 | 27 | default: 28 | color = RED; 29 | break; 30 | 31 | } 32 | 33 | byte brightness = sin8_C( millis() & 0xff ); // throb at about 4 Hz (1000 millis / 256 steps-per-sin8_C-cycle) 34 | 35 | setColor( dim( color , brightness ) ); 36 | 37 | 38 | } 39 | -------------------------------------------------------------------------------- /libraries/Examples01/library.properties: -------------------------------------------------------------------------------- 1 | name=01. Getting Started 2 | version=1.0 3 | author=Move38.com 4 | maintainer=Move38.com 5 | sentence=See something blink 6 | paragraph= 7 | category=Other 8 | url=https://github.com/bigjosh/Move38-Arduino-Platform 9 | architectures=avr 10 | types=Arduino 11 | -------------------------------------------------------------------------------- /libraries/Examples02/dummy.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Atmel Corp./Thibaut VIARD. All right reserved. 3 | 4 | This library is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU Lesser General Public 6 | License as published by the Free Software Foundation; either 7 | version 2.1 of the License, or (at your option) any later version. 8 | 9 | This library is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 | See the GNU Lesser General Public License for more details. 13 | 14 | You should have received a copy of the GNU Lesser General Public 15 | License along with this library; if not, write to the Free Software 16 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | */ 18 | 19 | /* 20 | * Workaround dummy file to obtain the examples present in the IDE menu File->Examples 21 | */ 22 | -------------------------------------------------------------------------------- /libraries/Examples02/examples/A-ColorByNeighbor/A-ColorByNeighbor.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * Color By Number/Neighbor 3 | * 4 | * An example showing how to count the number of neighbors. 5 | * 6 | * Each Blink displays a color based on the number of neighbors around it. 7 | * 8 | */ 9 | 10 | // color by number of neighbors 11 | Color colors[] = { 12 | dim(WHITE,40), // 0 neighbors 13 | RED, // 1 neighbors 14 | YELLOW, // 2 neighbors 15 | GREEN, // 3 neighbors 16 | CYAN, // 4 neighbors 17 | BLUE, // 5 neighbors 18 | MAGENTA, // 6 neighbors 19 | }; 20 | 21 | void setup() { 22 | // Blank 23 | } 24 | 25 | 26 | void loop() { 27 | 28 | // count neighbors we have right now 29 | int numNeighbors = 0; 30 | 31 | FOREACH_FACE(f) { 32 | 33 | if ( !isValueReceivedOnFaceExpired( f ) ) { // Have we seen an neighbor on this face recently? 34 | numNeighbors++; 35 | } 36 | 37 | } 38 | 39 | // look up the color to show based on number of neighbors 40 | // No need to bounds check here since we know we can never see more than 6 neighbors 41 | // because we only have 6 sides. 42 | 43 | setColor( colors[ numNeighbors ] ); 44 | 45 | } 46 | -------------------------------------------------------------------------------- /libraries/Examples02/examples/B-ColorRamps/B-ColorRamps.ino: -------------------------------------------------------------------------------- 1 | /// Show some soothing color ramps. 2 | 3 | void setup() { 4 | 5 | // No setup needed for this simple example! 6 | 7 | } 8 | 9 | 10 | // There are 255 brightness levels in each ramp. 11 | // We step 30 levels every 10 milliseconds, so... 12 | // Each ramp will take about ((100 ms/step)/(1000 ms/sec)) / ( (255 levels/ramp ) / ( 30 levels/step) ) = 13 | // ~1.17 secs/ramp 14 | // We do an up ramp and then a down ramp for each color 15 | 16 | #define STEP_SIZE 10 17 | #define STEP_TIME_MS 30 18 | 19 | Color colors[] = { BLUE , RED , GREEN }; 20 | 21 | byte colorIndex = 0; 22 | 23 | int brightness = 1; 24 | 25 | int step = STEP_SIZE; 26 | 27 | Timer nextStepTimer; 28 | 29 | void loop() { 30 | 31 | if (nextStepTimer.isExpired()) { 32 | 33 | // Change direction if we hit either boundary 34 | 35 | if ( (brightness + step > MAX_BRIGHTNESS ) || (brightness + step < 0 ) ) { 36 | 37 | step = -step; 38 | 39 | if (step>0) { // If we hit bottom, then time to move on to next color 40 | 41 | colorIndex++; 42 | 43 | if (colorIndex >= COUNT_OF( colors ) ) { 44 | 45 | colorIndex =0; 46 | 47 | } 48 | 49 | 50 | } 51 | 52 | 53 | } 54 | 55 | brightness += step; 56 | 57 | setColor( dim( colors[colorIndex] , brightness ) ); 58 | 59 | nextStepTimer.set( STEP_TIME_MS ); 60 | 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /libraries/Examples02/examples/C-SerialNumberPrinter/C-SerialNumberPrinter.ino: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | NOTE: This sketch is only interesting if you have a Blinks Dev Candy adapter connecting 4 | the blink to your serial port! 5 | 6 | Every blink tile comes into this world with its own untique serial number. 7 | 8 | This sketch prints the current tile's serial number out to the serial port. 9 | 10 | The serial number is 9 bytes long, and is printed with hex numbers like this... 11 | 12 | "For a good time, call:39-11-1-50-4E-38-33-33-39" 13 | 14 | ...or... 15 | 16 | "For a good time, call:30-20-3-50-4E-38-33-33-39" 17 | 18 | The first bytes are more likely to be different than the last bytes, in case 19 | you can't remember the whole thing (it is long). 20 | 21 | */ 22 | 23 | 24 | 25 | #include "Serial.h" 26 | 27 | ServicePortSerial sp; 28 | 29 | void setup() { 30 | 31 | sp.begin(); 32 | 33 | } 34 | 35 | void loop() { 36 | 37 | sp.print("For a good time, call:"); 38 | 39 | // First load the serial number buytes into a buffer 40 | 41 | byte snBuffer[SERIAL_NUMBER_LEN]; 42 | 43 | for( byte i=0; i trigger_time_ms + fade_time_ms ) { 39 | return 0; 40 | } 41 | 42 | word age_ms = millis() - trigger_time_ms; 43 | 44 | //word brightness = fade_time_ms - age_ms; 45 | 46 | word inverted_brightness = map( age_ms , 0 , fade_time_ms , 0 , 255 ); 47 | 48 | return 255-inverted_brightness; 49 | 50 | } 51 | 52 | public: 53 | 54 | inline void trigger(void) { 55 | 56 | trigger_time_ms = millis(); 57 | 58 | } 59 | 60 | inline void show() { 61 | setFaceColor( face , dim( color , get_current_brightness() ) ); 62 | } 63 | 64 | 65 | inline void update(void ) { 66 | 67 | if ( (*testFunction)() ) { 68 | 69 | trigger(); 70 | 71 | } 72 | 73 | } 74 | 75 | fadingIndicator_t( byte face, Color color , bool (*testFunction)() ) : face(face), color(color) , testFunction( testFunction ) {} 76 | 77 | }; 78 | 79 | fadingIndicator_t indicators[] { 80 | 81 | { 0 , RED , buttonPressed }, 82 | { 1 , GREEN , buttonReleased }, 83 | { 2 , BLUE , buttonSingleClicked }, 84 | { 3 , MAGENTA, buttonDoubleClicked }, 85 | { 4 , YELLOW , buttonMultiClicked }, 86 | { 5 , CYAN , buttonLongPressed }, 87 | 88 | }; 89 | 90 | 91 | void loop() { 92 | 93 | for(auto &item : indicators ) { 94 | 95 | item.update(); 96 | item.show(); 97 | 98 | } 99 | 100 | } 101 | -------------------------------------------------------------------------------- /libraries/Examples02/examples/F-SimpleDatagramDemo/F-SimpleDatagramDemo.ino: -------------------------------------------------------------------------------- 1 | // SimpleDatagramDemo 2 | // Simplest example of how to send and recieve datagrams over the IR link. 3 | // Face shows: 4 | // GREEN when it sees a neighboor and is getting a valid value from it (the number `42` is sent in this demo) 5 | // CYAN when it sees a neighboor and is getting an invalid value from it (anything other than the number `42` in this demo) 6 | // BLUE blink for 250ms when it sees a valid datagram (the three bytes {'C','A','T'} in the demo) 7 | // RED blink for 250ms when it sees an invalid datagram (anything but the three bytes {'C','A','T'} in the demo) 8 | // 9 | // Pressing the button sends the sample datagram on all faces 10 | 11 | // A datagram is a multibyte message that is sent on a best-efforts basis 12 | // Each datagram sent will be recieved at most one time (it might never be recieved) 13 | // Datagrams can be up to `IR_DATAGRAM_LEN` bytes long 14 | 15 | // Send somethign on all faces so we can check that we got it 16 | 17 | #define MAGIC_VALUE 42 18 | 19 | // Leave the current color on this face until this timer expires 20 | static Timer showColorOnFaceTimer[ FACE_COUNT ]; 21 | 22 | #define SHOW_COLOR_TIME_MS 250 // Long enough to see 23 | 24 | byte sampleDatagram[] { 'C' , 'A' , 'T' }; // A sample 3 byte long datagram 25 | 26 | 27 | void setup() { 28 | setValueSentOnAllFaces(MAGIC_VALUE); 29 | } 30 | 31 | 32 | /* 33 | * Compare memory regions. Returns 0 if all bytes in the blocks match. 34 | * Lifted from https://github.com/f32c/arduino/blob/master/hardware/fpga/f32c/system/src/memcmp.c 35 | */ 36 | 37 | int memcmp(const void *s1, const void *s2, unsigned n) 38 | { 39 | if (n != 0) { 40 | const unsigned char *p1 = s1, *p2 = s2; 41 | 42 | do { 43 | if (*p1++ != *p2++) 44 | return (*--p1 - *--p2); 45 | } while (--n != 0); 46 | } 47 | return (0); 48 | } 49 | 50 | 51 | void loop() { 52 | 53 | // First check all faces for an incoming datagram 54 | 55 | FOREACH_FACE(f) { 56 | 57 | if ( isDatagramReadyOnFace( f ) ) { 58 | 59 | const byte *datagramPayload = getDatagramOnFace(f); 60 | 61 | // Check that the length and all of the data btyes of the recieved datagram match what we were expecting 62 | // Note that `memcmp()` returns 0 if it is a match 63 | 64 | if ( getDatagramLengthOnFace(f)==sizeof( sampleDatagram ) && !memcmp( datagramPayload , sampleDatagram , sizeof( sampleDatagram )) ) { 65 | 66 | // This is the datagram we are looking for! 67 | 68 | setColorOnFace( BLUE , f ); 69 | 70 | } else { 71 | 72 | // Oops, we goty a datagram, but not the one we are loooking for 73 | 74 | setColorOnFace( RED , f ); 75 | 76 | } 77 | 78 | 79 | showColorOnFaceTimer[f].set( SHOW_COLOR_TIME_MS ); 80 | 81 | // We are done with the datagram, so free up the buffer so we can get another on this face 82 | markDatagramReadOnFace( f ); 83 | 84 | 85 | } else if ( showColorOnFaceTimer[f].isExpired() ) { 86 | 87 | if ( !isValueReceivedOnFaceExpired( f ) ) { 88 | 89 | // Show green if we do have a neighbor 90 | 91 | if (getLastValueReceivedOnFace(f) == MAGIC_VALUE ) { 92 | 93 | setColorOnFace( GREEN , f ); 94 | 95 | } else { 96 | 97 | setColorOnFace( CYAN, f ); 98 | 99 | 100 | } 101 | 102 | } else { 103 | 104 | // Or off if no neighbor 105 | 106 | setColorOnFace( OFF , f ); 107 | 108 | } 109 | 110 | } 111 | 112 | } 113 | 114 | 115 | if (buttonPressed()) { 116 | 117 | // When the button is click, trigger a datagram send on all faces 118 | 119 | FOREACH_FACE(f) { 120 | 121 | sendDatagramOnFace( &sampleDatagram , sizeof( sampleDatagram ) , f ); 122 | 123 | } 124 | 125 | } 126 | 127 | } // loop() 128 | -------------------------------------------------------------------------------- /libraries/Examples02/examples/G-IRButtonPressTester/G-IRButtonPressTester.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * IR Button Press 3 | * 4 | * Great for testing if blinks work and can communicate over IR 5 | * 6 | * Each face shows: 7 | * YELLOW - No neighbor on this face 8 | * BLUE - Neighbor button UP 9 | * GREEN - Neighbor button DOWN 10 | * RED - Error. Saw unexpected datum on this face. Resets after 0.5 second. 11 | * 12 | */ 13 | 14 | 15 | void setup() { 16 | // Blank 17 | } 18 | 19 | // Pick some unlikely values so we are more likely to show an error if a different 20 | // game is runnning on the oposing blink 21 | 22 | #define VALUE_BUTTON_UP 12 23 | #define VALUE_BUTTON_DOWN 21 24 | 25 | // Did we get an error onthis face recently? 26 | Timer errorOnFaceTimer[ FACE_COUNT ]; 27 | 28 | const int showErrTime_ms = 500; // Show the errror for 0.5 second so people can see it 29 | 30 | void loop() { 31 | 32 | // Make a little pulsation so we know it is working 33 | 34 | uint8_t brightness = sin8_C( (millis()/4) & 0xff ); 35 | 36 | FOREACH_FACE(f) { 37 | 38 | Color color; 39 | 40 | // Set the color on this face based on what we see... 41 | 42 | if ( !isValueReceivedOnFaceExpired( f ) ) { // Have we seen an neighbor on this face recently? 43 | 44 | switch ( getLastValueReceivedOnFace( f ) ) { 45 | 46 | case VALUE_BUTTON_UP : 47 | color = BLUE; 48 | break; 49 | 50 | case VALUE_BUTTON_DOWN: 51 | color=GREEN; 52 | break; 53 | 54 | default: 55 | // anything else is an error 56 | // We set a timer so this face will show red for a little while to make sure it is seen 57 | errorOnFaceTimer[f].set( showErrTime_ms ); 58 | break; 59 | 60 | } 61 | 62 | } else { 63 | 64 | // No neighbor on this face right now 65 | 66 | color=YELLOW; 67 | 68 | } 69 | 70 | // The red (error) will cover any other color on the face unil the timer times out 71 | 72 | if ( !errorOnFaceTimer[f].isExpired() ) { 73 | 74 | color = RED; 75 | 76 | } 77 | 78 | setColorOnFace( dim( color , brightness ) , f ); 79 | 80 | } 81 | 82 | // Finally update the value we send to others to match our current button state 83 | 84 | 85 | if ( buttonDown() ) { 86 | 87 | setValueSentOnAllFaces( VALUE_BUTTON_DOWN ) ; 88 | 89 | } else { 90 | 91 | setValueSentOnAllFaces( VALUE_BUTTON_UP ) ; 92 | 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /libraries/Examples02/examples/H-IRLinkTester/H-IRLinkTester.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * IR Link Tester 3 | * 4 | * Great for testing if blinks work and can communicate over IR 5 | * 6 | * Sends a series of messages with sequence numbers so it can detect a missed message. 7 | * The messages also have a checksum so it can detect corrupted messages. 8 | * 9 | * Each face shows: 10 | * BLUE - No neighbor on this face 11 | * GREEN - Blinks to show good data being received 12 | * ORANGE - Shows that a message was missed 13 | * RED - Shows that an invalid message was received. 14 | * 15 | * Press the button to clear ORANGE and RED. 16 | * 17 | */ 18 | 19 | 20 | // Use unsigned long becuase they tak a long time to wrap and have lots of bits that can have errors 21 | 22 | typedef unsigned SeqType; 23 | 24 | struct MessageType { 25 | byte txFace; // The face of the sending blink 26 | SeqType seq; 27 | SeqType inverted; // Inverted bits check 28 | }; 29 | 30 | // Next seq to send. 31 | SeqType nextSeqOut[ FACE_COUNT ]; 32 | 33 | // Next expected 34 | SeqType nextSeqIn[ FACE_COUNT ]; 35 | 36 | // Did we get an error on this face recently? 37 | bool showErrorFlag[ FACE_COUNT ]; 38 | 39 | // Did we miss a message on this face recently? 40 | bool showMissedFlag[ FACE_COUNT ]; 41 | 42 | 43 | // When should we do next blind send? 44 | // Note that we also send faster by ping ponging when we get a message in 45 | Timer nextSendTimer[ FACE_COUNT ]; 46 | 47 | // Has it been so long ince we saw something that we should give up showing is as present? 48 | Timer expireFaceTimer[ FACE_COUNT ]; 49 | 50 | //const int ErrorShowTime_ms = 500; // 51 | //const int MissedShowTime_ms = 250; // 52 | 53 | const int ResendTime_ms = 300; // Show the errror for 0.5 second so people can see it 54 | const int ExpireTime_ms = 1000; 55 | 56 | 57 | // Remember the pervious face seen so we don't generate a miss when a dffifernt face is swapped in 58 | byte lastTxFace[FACE_COUNT]; 59 | 60 | 61 | void setup() { 62 | 63 | FOREACH_FACE(f) { 64 | nextSeqOut[f]=0x5566; 65 | nextSeqIn[f]=0x5566; 66 | } 67 | 68 | } 69 | 70 | void loop() { 71 | 72 | if (buttonPressed()) { 73 | 74 | FOREACH_FACE(f) { 75 | 76 | showErrorFlag[f] = false; 77 | showMissedFlag[f] = false; 78 | 79 | } 80 | } 81 | 82 | 83 | 84 | FOREACH_FACE(f) { 85 | 86 | // If we have been asleep, then start everything fresh 87 | if (hasWoken()) { 88 | 89 | nextSendTimer[f].set(0); 90 | expireFaceTimer[f].set(0); 91 | 92 | } 93 | 94 | boolean sendNowFlag = false; 95 | 96 | // *** Incomming 97 | 98 | if ( isDatagramReadyOnFace( f ) ) { 99 | 100 | if ( getDatagramLengthOnFace(f) ==sizeof( MessageType ) ) { 101 | 102 | // We got a valid length message 103 | 104 | const MessageType *rxMessagePtr = (MessageType *) getDatagramOnFace(f); 105 | 106 | if ( rxMessagePtr->seq != ~rxMessagePtr->inverted ) { 107 | 108 | // Currupted data. Bad. 109 | 110 | //showErrorTimer[f].set( ErrorShowTime_ms ); 111 | showErrorFlag[f] = true; 112 | 113 | } else { 114 | 115 | // If we get here, then packet is the right length and the checksum is correct (valid packet) 116 | 117 | // If the face is expired, or this is a new face from the last message, then no need to show an error on the first message, just sync to it. 118 | 119 | // We check if the seq matches either the expected seq or +1 or +2. This way, we need to miss three or more consecutive packets to show an error. 120 | 121 | if ( !expireFaceTimer[f].isExpired() && lastTxFace[f] == rxMessagePtr->txFace && rxMessagePtr->seq !=nextSeqIn[f] && rxMessagePtr->seq != (nextSeqIn[f]+1) && rxMessagePtr->seq != (nextSeqIn[f]+2) ) { 122 | 123 | showMissedFlag[f] = true; 124 | 125 | } 126 | 127 | // NOTE: Here we depend on overflow to wrap 128 | nextSeqIn[f] = (rxMessagePtr->seq) + 1; // Sync to incomming message 129 | 130 | lastTxFace[f] = rxMessagePtr->txFace; 131 | 132 | } 133 | 134 | // We got something, so we know someone is there 135 | expireFaceTimer[f].set( ExpireTime_ms ); 136 | 137 | // Also send our response immedeately (ping pong) 138 | sendNowFlag = true; 139 | 140 | 141 | } else { 142 | 143 | // Invalid packet length 144 | // TODO: Should this be a different kind of error? 145 | 146 | //showErrorTimer[f].set( ErrorShowTime_ms ); 147 | showErrorFlag[f] = true; 148 | 149 | 150 | } 151 | 152 | markDatagramReadOnFace(f); 153 | 154 | } 155 | 156 | // *** Outgoing 157 | 158 | if (sendNowFlag || nextSendTimer[f].isExpired()) { 159 | 160 | MessageType txMessage; 161 | 162 | // NOTE: Here we depend on overflow to wrap 163 | 164 | txMessage.txFace = f; 165 | txMessage.seq = nextSeqOut[f]; 166 | txMessage.inverted = ~nextSeqOut[f]; 167 | 168 | sendDatagramOnFace( &txMessage , sizeof( txMessage ) , f ); 169 | 170 | nextSeqOut[f]++; 171 | 172 | nextSendTimer[f].set( ResendTime_ms ); 173 | 174 | } 175 | 176 | // *** Display 177 | 178 | 179 | if ( showErrorFlag[f]) { 180 | 181 | setColorOnFace( RED , f ); 182 | 183 | } else if ( showMissedFlag[f]) { 184 | 185 | setColorOnFace( dim( ORANGE , 128 ) , f ); 186 | 187 | } else if (expireFaceTimer[f].isExpired() ) { 188 | 189 | // No partner on this face, so show blue 190 | 191 | setColorOnFace( dim( BLUE , 128 ) , f ); 192 | 193 | } else { 194 | 195 | // Otherwise, everything is hunky-dory 196 | 197 | // Make the green pulse to show the speed of transmitions and also just give a feel that data is really flowing 198 | 199 | //uint8_t brightness = sin8_C( ( nextSeqIn[f] * 16 ) & 0xff ); 200 | 201 | uint8_t brightness = (( nextSeqIn[f] & 0x01 ) * 128 ) + 127; 202 | 203 | setColorOnFace( dim( GREEN , brightness ) , f ); 204 | 205 | } 206 | 207 | 208 | } 209 | 210 | } 211 | -------------------------------------------------------------------------------- /libraries/Examples02/library.properties: -------------------------------------------------------------------------------- 1 | name=02. Getting Practical 2 | version=1.0 3 | author=Move38.com 4 | maintainer=Move38.com 5 | sentence=See something blink 6 | paragraph= 7 | category=Other 8 | url=https://github.com/bigjosh/Move38-Arduino-Platform 9 | architectures=avr 10 | types=Arduino 11 | -------------------------------------------------------------------------------- /libraries/Examples03/dummy.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Atmel Corp./Thibaut VIARD. All right reserved. 3 | 4 | This library is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU Lesser General Public 6 | License as published by the Free Software Foundation; either 7 | version 2.1 of the License, or (at your option) any later version. 8 | 9 | This library is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 | See the GNU Lesser General Public License for more details. 13 | 14 | You should have received a copy of the GNU Lesser General Public 15 | License along with this library; if not, write to the Free Software 16 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | */ 18 | 19 | /* 20 | * Workaround dummy file to obtain the examples present in the IDE menu File->Examples 21 | */ 22 | -------------------------------------------------------------------------------- /libraries/Examples03/examples/Berry/Berry.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * Berry 3 | * by VV Studio 4 | * at IndieCade East 2018 Game Jam 5 | * Lead development by Jonathan Bobrow, Move38 Inc. 6 | * original game by ViVi and Vanilla 7 | * 8 | * Rules: https://github.com/Move38/Berry/blob/master/README.md 9 | * 10 | * -------------------- 11 | * Blinks by Move38 12 | * Brought to life via Kickstarter 2018 13 | * 14 | * @madewithblinks 15 | * www.move38.com 16 | * -------------------- 17 | */ 18 | 19 | Color colors[] = { BLUE, RED, YELLOW }; 20 | byte currentColorIndex = 0; 21 | byte faceIndex = 0; 22 | byte faceStartIndex = 0; 23 | 24 | bool isWaiting = false; 25 | 26 | #define FACE_DURATION 60 27 | #define WAIT_DURATION 2000 28 | 29 | Timer faceTimer; 30 | Timer waitTimer; 31 | 32 | void setup() { 33 | // put your setup code here, to run once: 34 | 35 | } 36 | 37 | void loop() { 38 | // put your main code here, to run repeatedly: 39 | 40 | if ( buttonSingleClicked() ) { 41 | 42 | currentColorIndex++; 43 | 44 | if (currentColorIndex >= COUNT_OF(colors)) { 45 | currentColorIndex = 0; 46 | } 47 | 48 | } 49 | 50 | if ( waitTimer.isExpired() ) { 51 | if ( faceTimer.isExpired() ) { 52 | faceTimer.set( FACE_DURATION ); 53 | faceIndex++; 54 | 55 | if (faceIndex >= 7) { 56 | faceIndex = 0; 57 | waitTimer.set( WAIT_DURATION ); 58 | isWaiting = true; 59 | 60 | // shift the starting point 61 | faceStartIndex++; 62 | if (faceStartIndex >= 6) { 63 | faceStartIndex = 0; 64 | } 65 | } 66 | else { 67 | isWaiting = false; 68 | } 69 | } 70 | } 71 | 72 | // display color 73 | setColor( colors[currentColorIndex] ); 74 | 75 | // show locked sides 76 | if (isPositionLocked()) { 77 | // show the state of locked animation on all faces 78 | byte bri = 153 + (sin8_C((millis() / 6) % 255)*2)/5; 79 | setColor(dim(colors[currentColorIndex], bri)); 80 | } 81 | 82 | // show next color 83 | if (!isWaiting) { 84 | byte nextColorIndex = (currentColorIndex + 1) % 3; 85 | byte face = (faceStartIndex + faceIndex - 1) % FACE_COUNT; 86 | setFaceColor( face, colors[nextColorIndex] ); 87 | } 88 | } 89 | 90 | bool isPositionLocked() { 91 | // based on the arrangement of neighbors, am I locked... 92 | bool neighborPattern[6]; 93 | bool lockedA[6] = {1, 0, 1, 0, 1, 0}; 94 | bool lockedB[6] = {1, 0, 1, 0, 0, 0}; 95 | 96 | FOREACH_FACE(f) { 97 | neighborPattern[f] = !isValueReceivedOnFaceExpired(f); 98 | } 99 | 100 | // neighbors across from each other 101 | for (byte i = 0; i < 3; i++) { 102 | if (neighborPattern[i] && neighborPattern[i + 3]) { 103 | return true; 104 | } 105 | } 106 | 107 | // special case lock patterns 108 | if ( isThisPatternPresent(lockedA, neighborPattern)) { 109 | return true; 110 | } 111 | if ( isThisPatternPresent(lockedB, neighborPattern)) { 112 | return true; 113 | } 114 | 115 | return false; 116 | } 117 | 118 | // check to see if pattern is in the array 119 | // return true if the pattern is in fact in the array 120 | // pattern is always 6 bools 121 | // source is always 12 bools (2 x 6 bools) 122 | bool isThisPatternPresent( bool pat[], bool source[]) { 123 | 124 | // first double the source to be cyclical 125 | bool source_double[12]; 126 | 127 | for (byte i = 0; i < 12; i++) { 128 | source_double[i] = source[i % 6]; 129 | } 130 | 131 | // then find the pattern 132 | byte pat_index = 0; 133 | 134 | for (byte i = 0; i < 12; i++) { 135 | if (source_double[i] == pat[pat_index]) { 136 | // increment index 137 | pat_index++; 138 | 139 | if ( pat_index == 6 ) { 140 | // found the entire pattern 141 | return true; 142 | } 143 | } 144 | else { 145 | // set index back to 0 146 | pat_index = 0; 147 | } 148 | } 149 | 150 | return false; 151 | } 152 | -------------------------------------------------------------------------------- /libraries/Examples03/examples/FlicFlop/FlicFlop.ino: -------------------------------------------------------------------------------- 1 | /* 2 | FlicFlop 3 | by Move38, Inc. 2019 4 | Lead development by Dan King 5 | original game by Nick Bentley, Jonathan Bobrow, Dan King 6 | 7 | Rules: https://github.com/Move38/Astro/blob/master/README.md 8 | 9 | -------------------- 10 | Blinks by Move38 11 | Brought to life via Kickstarter 2018 12 | 13 | @madewithblinks 14 | www.move38.com 15 | -------------------- 16 | */ 17 | 18 | enum gameStates {FLICKER_UNSCORED, FLICKER_SCORED, FLICKER_DISPLAY, FLOPPER}; 19 | byte gameState = FLICKER_UNSCORED; 20 | bool longPressCheck = false; 21 | 22 | #define TEAM_COUNT 3 23 | byte scoringTeam = 0; 24 | byte signalTeam = 0; 25 | 26 | enum celebrationStates {INERT, CELEBRATE, TRANSITION}; 27 | byte celebrationState = INERT; 28 | 29 | Timer flopTimer; 30 | #define FLOP_INTERVAL 2000 31 | 32 | 33 | Timer animTimer; 34 | #define ANIMATION_INTERVAL 200 35 | byte animationInterval = ANIMATION_INTERVAL; 36 | 37 | #define ANIMATION_CELEBRATE_INTERVAL 20 38 | Timer celebrationTimer; 39 | #define CELEBRATE_TIME 2000 40 | 41 | byte spinFace = 0; 42 | byte teamHues[4] = {0, 45, 125, 230}; 43 | 44 | void setup() { 45 | // put your setup code here, to run once: 46 | 47 | } 48 | 49 | void loop() { 50 | 51 | if (hasWoken()) { 52 | longPressCheck = false; 53 | } 54 | 55 | // put your main code here, to run repeatedly: 56 | if (gameState == FLOPPER) { 57 | flopperLoop(); 58 | flopperDisplay(); 59 | } else { 60 | flickerLoop(); 61 | flickerDisplay(); 62 | } 63 | 64 | //animate the spin face 65 | spinFaceAnimator(); 66 | 67 | //set up communication 68 | byte sendData = (signalTeam << 4) + (scoringTeam << 2) + (celebrationState); 69 | setValueSentOnAllFaces(sendData); 70 | 71 | if (buttonSingleClicked()) { 72 | beginCelebration(); 73 | } 74 | 75 | celebrationLoop(); 76 | 77 | if (longPressCheck) { 78 | if (isAlone()) { 79 | setColor(WHITE); 80 | setColorOnFace(OFF, spinFace); 81 | } 82 | } 83 | 84 | //dump button presses 85 | buttonDoubleClicked(); 86 | buttonLongPressed(); 87 | } 88 | 89 | void flopperLoop() { 90 | 91 | //look for other floppers trying to move us along to the next color 92 | bool hasFlopperNeighbor = false; 93 | bool shouldChange = false; 94 | byte changeTo = signalTeam; 95 | byte lastFlopperFace = 0; 96 | FOREACH_FACE(f) { 97 | if (!isValueReceivedOnFaceExpired(f)) { //a neighbor! 98 | byte neighborData = getLastValueReceivedOnFace(f); 99 | if (getScoringTeam(neighborData) == 0) {//this could be a flopper 100 | if (getSignalTeam(neighborData) != 0) {//it is a flopper 101 | //set the last flopper face 102 | lastFlopperFace = f; 103 | hasFlopperNeighbor = true; 104 | 105 | //check for signal change 106 | if (getSignalTeam(neighborData) == signalTeam + 1) {//it wants me to move 107 | shouldChange = true; 108 | changeTo = getSignalTeam(neighborData); 109 | } else if (signalTeam == 3 && getSignalTeam(neighborData) == 1) {//it wants me to move 110 | shouldChange = true; 111 | changeTo = 1; 112 | } 113 | } 114 | } 115 | } 116 | } 117 | 118 | if (shouldChange) { 119 | signalTeam = changeTo; 120 | flopTimer.set(FLOP_INTERVAL); 121 | //change the spinface 122 | //spinFace = lastFlopperFace; 123 | //animTimer.set(0); 124 | } 125 | 126 | if (flopTimer.isExpired()) { 127 | signalTeam = (signalTeam % TEAM_COUNT) + 1; 128 | flopTimer.set(FLOP_INTERVAL); 129 | //if (hasFlopperNeighbor) { 130 | //spinFace = lastFlopperFace; 131 | //animTimer.set(0); 132 | //} 133 | } 134 | 135 | //change to flicker? 136 | if (buttonLongPressed()) { 137 | if (isAlone()) { 138 | //set the transition boolean to true 139 | longPressCheck = true; 140 | beginCelebration(); 141 | } 142 | } 143 | 144 | if (buttonReleased()) { 145 | if (longPressCheck) { 146 | longPressCheck = false;//regardless of outcome, this needs to be false 147 | if (isAlone()) { 148 | scoringTeam = 0; 149 | signalTeam = 0; 150 | gameState = FLICKER_UNSCORED; 151 | } 152 | } 153 | } 154 | 155 | } 156 | 157 | void flickerLoop() { 158 | 159 | if (gameState == FLICKER_UNSCORED) { 160 | //listen for neighbors with signal teams 161 | //become that signal team 162 | FOREACH_FACE(f) { 163 | if (!isValueReceivedOnFaceExpired(f)) { //a neighbor! 164 | byte neighborData = getLastValueReceivedOnFace(f); 165 | 166 | if (getSignalTeam(neighborData) != 0) {//this guy is signalling 167 | 168 | //become scored 169 | gameState = FLICKER_SCORED; 170 | scoringTeam = getSignalTeam(neighborData); 171 | signalTeam = scoringTeam; 172 | 173 | //kick off a celebration 174 | beginCelebration(); 175 | } 176 | } 177 | } 178 | 179 | //also, listen for long press to become flopper 180 | if (buttonLongPressed()) { 181 | if (isAlone()) { 182 | //set the transition boolean to true 183 | longPressCheck = true; 184 | beginCelebration(); 185 | } 186 | } 187 | 188 | if (buttonReleased()) { 189 | if (longPressCheck) { 190 | longPressCheck = false;//regardless of outcome, this needs to be false 191 | if (isAlone()) { 192 | gameState = FLOPPER; 193 | signalTeam = 1; 194 | scoringTeam = 0; 195 | } 196 | } 197 | } 198 | 199 | } else if (gameState == FLICKER_SCORED) { 200 | //listen for signals to change your signal 201 | FOREACH_FACE(f) { 202 | if (!isValueReceivedOnFaceExpired(f)) { 203 | byte neighborData = getLastValueReceivedOnFace(f); 204 | if (getSignalTeam(neighborData) == signalTeam + 1) { 205 | signalTeam = getSignalTeam(neighborData); 206 | } else if (signalTeam == 3 && getSignalTeam(neighborData) == 1) { 207 | signalTeam = 1; 208 | } 209 | } 210 | 211 | if (isAlone()) { 212 | gameState = FLICKER_DISPLAY; 213 | signalTeam = 0; 214 | } 215 | } 216 | 217 | } else if (gameState == FLICKER_DISPLAY) { 218 | //listen for things with signal teams to rejoin the game 219 | //listen for things with no scoring team to go back to unscored 220 | FOREACH_FACE(f) { 221 | if (!isValueReceivedOnFaceExpired(f)) {//neighbor! 222 | byte neighborData = getLastValueReceivedOnFace(f); 223 | 224 | if (getSignalTeam(neighborData) != 0) { //I have rejoined the game because this neighbor has a signal team 225 | gameState = FLICKER_SCORED; 226 | signalTeam = getSignalTeam(neighborData); 227 | 228 | } else if (getScoringTeam(neighborData) == 0) { //this neighbor has no signal team, and also has no scoring team. Unscored! 229 | gameState = FLICKER_UNSCORED; 230 | scoringTeam = 0; 231 | 232 | } 233 | } 234 | } 235 | 236 | //we can also be double-clicked back to unscored 237 | if (buttonDoubleClicked()) { 238 | gameState = FLICKER_UNSCORED; 239 | scoringTeam = 0; 240 | } 241 | } 242 | 243 | } 244 | 245 | void beginCelebration() { 246 | animTimer.set(0); 247 | celebrationState = CELEBRATE; 248 | animationInterval = ANIMATION_CELEBRATE_INTERVAL; 249 | celebrationTimer.set(CELEBRATE_TIME); 250 | } 251 | 252 | void celebrationLoop() { 253 | //here we check for the INERT/CELEBRATE/TRANSITION stuff 254 | if (celebrationState == INERT) { 255 | FOREACH_FACE(f) { 256 | if (!isValueReceivedOnFaceExpired(f)) { 257 | if (getCelebrationState(getLastValueReceivedOnFace(f)) == CELEBRATE) { 258 | beginCelebration(); 259 | } 260 | } 261 | } 262 | } else if (celebrationState == CELEBRATE) { 263 | //only move on to TRANSITION if no neighbors are still INERT 264 | celebrationState = TRANSITION; 265 | FOREACH_FACE(f) { 266 | if (!isValueReceivedOnFaceExpired(f)) { 267 | if (getCelebrationState(getLastValueReceivedOnFace(f)) == INERT) { 268 | celebrationState = CELEBRATE;//revert the change from above 269 | } 270 | } 271 | } 272 | } else if (celebrationState == TRANSITION) { 273 | //only move to INERT if no neighbors are in CELEBRATE 274 | celebrationState = INERT; 275 | FOREACH_FACE(f) { 276 | if (!isValueReceivedOnFaceExpired(f)) { 277 | if (getCelebrationState(getLastValueReceivedOnFace(f)) == CELEBRATE) { 278 | celebrationState = TRANSITION;//revert the change from above 279 | } 280 | } 281 | } 282 | } 283 | 284 | //set the animation interval correctly based on the celebration timer 285 | if (celebrationTimer.isExpired()) { 286 | animationInterval = ANIMATION_INTERVAL; 287 | } else { 288 | animationInterval = map(CELEBRATE_TIME - celebrationTimer.getRemaining(), 0, CELEBRATE_TIME, ANIMATION_CELEBRATE_INTERVAL, ANIMATION_INTERVAL); 289 | } 290 | } 291 | 292 | ///////////////// 293 | //DISPLAY LOOPS// 294 | ///////////////// 295 | 296 | void spinFaceAnimator() { 297 | if (animTimer.isExpired()) { 298 | spinFace = (spinFace + 1) % 6; 299 | animTimer.set(animationInterval); 300 | } 301 | } 302 | 303 | void flopperDisplay() { 304 | setColor(makeColorHSB(teamHues[signalTeam], 255, 255)); 305 | bool multiFlopper = false; 306 | 307 | FOREACH_FACE(f) { 308 | if (!isValueReceivedOnFaceExpired(f)) { //a neighbor! 309 | byte neighborData = getLastValueReceivedOnFace(f); 310 | if (getScoringTeam(neighborData) == 0) { //it's another FLOPPER 311 | //am I celebrating? 312 | if (animationInterval < ANIMATION_INTERVAL) { //I am celebrating 313 | setColorOnFace(makeColorHSB(teamHues[signalTeam], 255, 255), f); 314 | } else {//not celebrating 315 | setColorOnFace(OFF, f); 316 | } 317 | multiFlopper = true; 318 | } 319 | } 320 | } 321 | 322 | if (!multiFlopper) { 323 | setColorOnFace(OFF, spinFace); 324 | } 325 | } 326 | 327 | void flickerDisplay() { 328 | setColor(OFF); 329 | 330 | if (gameState == FLICKER_UNSCORED) { 331 | setColorOnFace(WHITE, spinFace); 332 | } else if (gameState == FLICKER_SCORED) { 333 | setColorOnFace(makeColorHSB(teamHues[scoringTeam], 255, 255), spinFace); 334 | setColorOnFace(makeColorHSB(teamHues[signalTeam], 255, 255), (spinFace + 2) % 6); 335 | setColorOnFace(makeColorHSB(teamHues[signalTeam], 255, 255), (spinFace + 3) % 6); 336 | setColorOnFace(makeColorHSB(teamHues[signalTeam], 255, 255), (spinFace + 4) % 6); 337 | } else if (gameState == FLICKER_DISPLAY) { 338 | setColorOnFace(makeColorHSB(teamHues[scoringTeam], 255, 255), spinFace); 339 | setColorOnFace(makeColorHSB(teamHues[scoringTeam], 255, 255), (spinFace + 2) % 6); 340 | setColorOnFace(makeColorHSB(teamHues[scoringTeam], 255, 255), (spinFace + 4) % 6); 341 | } 342 | } 343 | 344 | ///////////////////////// 345 | //CONVENIENCE FUNCTIONS// 346 | ///////////////////////// 347 | 348 | byte getSignalTeam(byte data) { 349 | return (data >> 4);//first and second bit 350 | } 351 | 352 | byte getScoringTeam(byte data) { 353 | return ((data >> 2) & 3);//third and fourth bit 354 | } 355 | 356 | byte getCelebrationState(byte data) { 357 | return (data & 3);//5th and 6th bit 358 | } 359 | -------------------------------------------------------------------------------- /libraries/Examples03/examples/Fracture/Fracture.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * Fracture 3 | * by Move38, Inc. 2019 4 | * Lead development by Jonathan Bobrow, Daniel King 5 | * original game by Celia Pearce, Em Lazer-Walker, Jonathan Bobrow, Joshua Sloane 6 | * 7 | * Rules: https://github.com/Move38/Fracture/blob/master/README.md 8 | * 9 | * -------------------- 10 | * Blinks by Move38 11 | * Brought to life via Kickstarter 2018 12 | * 13 | * @madewithblinks 14 | * www.move38.com 15 | * -------------------- 16 | */ 17 | 18 | #define HAPPY_FLASH_DURATION 500 19 | #define EDGE_FADE_DURAION 500 20 | #define SPARKLE_OFFSET 80 21 | #define SPARKLE_DURATION 800 22 | #define SPARKLE_CYCLE_DURATION 1600 23 | 24 | Color displayColor; 25 | 26 | //Color teamColors[] = {RED, BLUE, YELLOW, GREEN}; 27 | byte teamHues[6] = {22, 49, 82, 99, 160, 200}; 28 | 29 | byte teamIndex = 0; 30 | 31 | Timer happyFlashTimer; 32 | bool happyFlashOn; 33 | 34 | byte sparkleOffset[6] = {0, 3, 5, 1, 4, 2}; 35 | 36 | Timer edgeTimer[6]; 37 | bool edgeAcquired; 38 | 39 | bool hasRecentlySeenNeighbor[6]; 40 | 41 | void setup() { 42 | } 43 | 44 | void loop() { 45 | 46 | // change team if triple clicked 47 | if (buttonDoubleClicked()) { 48 | teamIndex++; 49 | if (teamIndex >= COUNT_OF(teamHues)) { 50 | teamIndex = 0; 51 | } 52 | } 53 | 54 | byte numNeighbors = 0; 55 | bool noNeighborsOfSameColor = true; 56 | 57 | // look at neighbors 58 | FOREACH_FACE(f) { 59 | if (!isValueReceivedOnFaceExpired(f)) { 60 | 61 | if (hasRecentlySeenNeighbor[f] == false) { 62 | edgeAcquired = true; 63 | edgeTimer[f].set(EDGE_FADE_DURAION); 64 | } 65 | hasRecentlySeenNeighbor[f] = true; 66 | 67 | numNeighbors++; 68 | 69 | // if their color is the same as mine... not happy 70 | if (getLastValueReceivedOnFace(f) == teamIndex) { 71 | noNeighborsOfSameColor = false; 72 | } 73 | } 74 | else { 75 | if (hasRecentlySeenNeighbor[f] == true) { 76 | edgeAcquired = false; 77 | edgeTimer[f].set(EDGE_FADE_DURAION); 78 | } 79 | hasRecentlySeenNeighbor[f] = false; 80 | } 81 | } 82 | 83 | bool isHappy = false; 84 | 85 | // if I have two neighbors or more and my neighbors are not my color i'm happy 86 | if (numNeighbors >= 2 && noNeighborsOfSameColor) { 87 | isHappy = true; 88 | } 89 | 90 | // if I'm happy 91 | if (isHappy) { 92 | displayHappy(); 93 | } 94 | else { 95 | displayNotHappy(); 96 | } 97 | 98 | // display fracture animation or mend animation 99 | FOREACH_FACE(f) { 100 | if (!edgeTimer[f].isExpired()) { 101 | if (edgeAcquired) { 102 | // if we just gained a neighbor saturate from white 103 | byte sat = 255 - (255 * edgeTimer[f].getRemaining() ) / EDGE_FADE_DURAION; 104 | setColorOnFace(makeColorHSB(teamHues[teamIndex], sat, 255), f); 105 | } 106 | else { 107 | // if we just lost a neighbor fade up from dark 108 | byte bri = 255 - (255 * edgeTimer[f].getRemaining() ) / EDGE_FADE_DURAION; 109 | setColorOnFace(makeColorHSB(teamHues[teamIndex], 255, bri), f); 110 | } 111 | } 112 | } 113 | 114 | setValueSentOnAllFaces(teamIndex); 115 | } 116 | 117 | void displayHappy() { 118 | 119 | // have the color on the Blink raise and lower to feel more alive 120 | byte bri = 185 + sin8_C( (millis() / 14) % 255) * 70 / 255; // oscillate between values 185and 255 121 | setColor(dim(getColorForTeam(teamIndex), bri)); 122 | 123 | // lets do a celebration on each face in an order 124 | word delta = millis() % SPARKLE_CYCLE_DURATION; // 2 second cycle 125 | 126 | if (delta > SPARKLE_DURATION) { 127 | delta = SPARKLE_DURATION; 128 | } 129 | 130 | FOREACH_FACE(f) { 131 | 132 | // if the face has started it's glow 133 | uint16_t sparkleStart = sparkleOffset[f] * SPARKLE_OFFSET; 134 | uint16_t sparkleEnd = sparkleStart + SPARKLE_DURATION - (6 * SPARKLE_OFFSET); 135 | 136 | if ( delta > sparkleStart ) { 137 | // minimum of 125, maximum of 255 138 | word phaseShift = 60 * f; 139 | byte amplitude = 55; 140 | byte midline = 185; 141 | byte rate = 6; 142 | byte lowBri = midline + (amplitude * sin8_C( (phaseShift + millis() / rate) % 255) / 100); 143 | byte brightness; 144 | byte saturation; 145 | 146 | if ( delta < sparkleEnd ) { 147 | brightness = map(delta, sparkleStart, sparkleStart + SPARKLE_DURATION - (6 * SPARKLE_OFFSET), 255, lowBri); 148 | saturation = map(delta, sparkleStart, sparkleStart + SPARKLE_DURATION - (6 * SPARKLE_OFFSET), 0, 255); 149 | } 150 | else { 151 | //brightness = lowBri; 152 | saturation = 255; 153 | } 154 | 155 | Color faceColor = makeColorHSB(teamHues[teamIndex], saturation, 255); 156 | setColorOnFace(faceColor, f); 157 | } 158 | } 159 | 160 | } 161 | 162 | void displayNotHappy() { 163 | // have the color on the Blink raise and lower to feel more alive 164 | byte bri = 185 + sin8_C( (millis() / 14) % 255) * 70 / 255; // oscillate between values 185and 255 165 | setColor(dim(getColorForTeam(teamIndex), bri)); 166 | } 167 | 168 | 169 | Color getColorForTeam(byte t) { 170 | return makeColorHSB(teamHues[t], 255, 255); 171 | } 172 | -------------------------------------------------------------------------------- /libraries/Examples03/library.properties: -------------------------------------------------------------------------------- 1 | name=03. Getting Playful 2 | version=1.0 3 | author=Move38.com 4 | maintainer=Move38.com 5 | sentence=12 Games for Blinks 6 | paragraph= 7 | category=Other 8 | url=https://github.com/Move38/Blinks-SDK 9 | architectures=avr 10 | types=Arduino 11 | -------------------------------------------------------------------------------- /libraries/Examples04/dummy.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Atmel Corp./Thibaut VIARD. All right reserved. 3 | 4 | This library is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU Lesser General Public 6 | License as published by the Free Software Foundation; either 7 | version 2.1 of the License, or (at your option) any later version. 8 | 9 | This library is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 | See the GNU Lesser General Public License for more details. 13 | 14 | You should have received a copy of the GNU Lesser General Public 15 | License along with this library; if not, write to the Free Software 16 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | */ 18 | 19 | /* 20 | * Workaround dummy file to obtain the examples present in the IDE menu File->Examples 21 | */ 22 | -------------------------------------------------------------------------------- /libraries/Examples04/library.properties: -------------------------------------------------------------------------------- 1 | name=04. Getting Testy 2 | version=1.0 3 | author=Move38.com 4 | maintainer=Move38.com 5 | sentence=See something blink 6 | paragraph= 7 | category=Other 8 | url=https://github.com/bigjosh/Move38-Arduino-Platform 9 | architectures=avr 10 | types=Arduino 11 | -------------------------------------------------------------------------------- /libraries/Examples05/dummy.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Atmel Corp./Thibaut VIARD. All right reserved. 3 | 4 | This library is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU Lesser General Public 6 | License as published by the Free Software Foundation; either 7 | version 2.1 of the License, or (at your option) any later version. 8 | 9 | This library is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 | See the GNU Lesser General Public License for more details. 13 | 14 | You should have received a copy of the GNU Lesser General Public 15 | License along with this library; if not, write to the Free Software 16 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | */ 18 | 19 | /* 20 | * Workaround dummy file to obtain the examples present in the IDE menu File->Examples 21 | */ 22 | -------------------------------------------------------------------------------- /libraries/Examples05/library.properties: -------------------------------------------------------------------------------- 1 | name=05. Getting Funky 2 | version=1.0 3 | author=Move38.com 4 | maintainer=Move38.com 5 | sentence=See something blink 6 | paragraph= 7 | category=Other 8 | url=https://github.com/bigjosh/Move38-Arduino-Platform 9 | architectures=avr 10 | types=Arduino 11 | -------------------------------------------------------------------------------- /linkscripts/readme.MD: -------------------------------------------------------------------------------- 1 | We use a shared data block for communication between the bootloader code and the foreground game. This lets us load that stuff once rather than having to include it in every game image. 2 | 3 | The shared memory block lives at a fixed location at the bottom of RAM. 4 | 5 | We need a custom link script so we can force that block to this known location. 6 | 7 | The linker scripts here were copied from... 8 | 9 | C:\Program Files (x86)\Arduino\hardware\tools\avr\avr\lib\ldscripts 10 | 11 | ...which seems to be hardcoded into `gcc`. 12 | 13 | We add a new group of sections called `ipcram1`-`ipcram9` which hold the shared memory block. 14 | 15 | Note also that we mark these sections as `KEEP`, but they still seem to get garbage collected if not referenced, so we should make sure to reference them in the foreground code or else the foreground will put variables here and overwrite the bootloader's info. 16 | 17 | We had to make a new `.dataX` segment because the origin of the normal `.data` segment seems to be hardcoded into the "specific device" file in gcc... 18 | 19 | https://electronics.stackexchange.com/questions/408115/how-does-avr-gcc-linker-know-to-put-the-datasection-at-0x800100-rather-than 20 | 21 | It is ok, becuase the new script is much cleaner than the stock one, and also moves the `bss` segment down so that both the `ipcram` memory and the normal static variables can all be initialized to `0` in one big block. Note that we only want to zero out the `ipcram` in the BIOS startup, so the linker script for user programs will put the `bss` start above here. 22 | 23 | Another hard won discovery is that if you put anything into .bss, it seems to output the whole thing to the HEX file. We fix this by adding `(NOLOAD)` to the segment. Phew. 24 | 25 | To get Arduino use this custom script, we edit the `platform.txt` to have... 26 | 27 | ``` 28 | recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" -Wl,-verbose -Wl,--script="{{build.core}/linkerscripts/avr5.xn" {compiler.c.elf.flags} -mmcu={build.mcu} {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" {object_files} "{build.path}/{archive_file}" "-L{build.path}" -lm 29 | ``` 30 | 31 | But it is better to pre-compile this BIOS code into a HEX file and then have the Arduino code blindly flash it using AVRDUDE during the download. To compile in AS7, we have to add this to the `Toolchain->Linker->Misc->Linker flags`... 32 | 33 | `-Wl,--script="../../../src/linkscripts/avr5.xn"` 34 | 35 | The `-Wl,` means "pass the next arg to the linker and the `--script=` [specifies the linker script](ftp://ftp.gnu.org/pub/old-gnu/Manuals/ld-2.9.1/html_chapter/ld_2.html#SEC3). This sucks that we have to hard code the `avr5` in there but I think the mapping from MCU to those `avrX` code is hardcoded into gcc. 36 | 37 | 38 | To put a variable into this new section, we use... 39 | 40 | ``` 41 | byte __attribute__((section ("ipcram1"))) counter=0; 42 | ``` 43 | 44 | More info: 45 | https://gcc.gnu.org/onlinedocs/gcc-3.2/gcc/Variable-Attributes.html 46 | 47 | ### Stack Overflow Detector 48 | 49 | We put the input section `.stackwatcher` after all the other stuff in the `data` memory section. We can then have the code put a special value here and periodically check that value to see if it changed. Since the stack grows down from the top of RAM, it will hit this first and so if anything here changes then we know that the stack got too big and overwrote it. 50 | 51 | -------------------------------------------------------------------------------- /package_move38.com-blinks_index.json: -------------------------------------------------------------------------------- 1 | { 2 | "packages": [ 3 | { 4 | "name": "move38", 5 | "maintainer": "Move38.com", 6 | "websiteURL": "http://move38.com", 7 | "email": "move38arduino@joshreply.com", 8 | 9 | "help": { 10 | "online": "https://github.com/bigjosh/Move38-Arduino-Platform" 11 | }, 12 | "platforms": [ 13 | { 14 | "name": "Blinks", 15 | "architecture": "avr", 16 | "version": "1.0.0", 17 | "category": "Contributed", 18 | "help": { 19 | "online": "https://github.com/bigjosh/Move38-Arduino-Platform" 20 | }, 21 | "url": "https://janedeveloper.github.io/myboard/myboard-1.0.0.zip", 22 | "archiveFileName": "myboard-1.0.0.zip", 23 | "checksum": "SHA-256:ec3ff8a1dc96d3ba6f432b9b837a35fd4174a34b3d2927de1d51010e8b94f9f1", 24 | "size": "15005", 25 | "boards": [ 26 | {"name": "Blinks Tile"}, 27 | ], 28 | "toolsDependencies": [ 29 | { 30 | "packager": "arduino", 31 | "name": "avr-gcc", 32 | "version": "4.8.1-arduino5" 33 | }, 34 | { 35 | "packager": "arduino", 36 | "name": "avrdude", 37 | "version": "6.0.1-arduino5" 38 | } 39 | ] 40 | }, 41 | { 42 | "name": "My Board", 43 | "architecture": "avr", 44 | "version": "1.0.1", 45 | "category": "Contributed", 46 | "help": { 47 | "online": "http://janedeveloper.org/forum/myboard" 48 | }, 49 | "url": "https://janedeveloper.github.io/myboard/myboard-1.0.1.zip", 50 | "archiveFileName": "myboard-1.0.1.zip", 51 | "checksum": "SHA-256:9c86ee28a7ce9fe33e8b07ec643316131e0031b0d22e63bb398902a5fdadbca9", 52 | "size": "15125", 53 | "boards": [ 54 | {"name": "My Board"}, 55 | {"name": "My Board Pro"} 56 | ], 57 | "toolsDependencies": [ 58 | { 59 | "packager": "arduino", 60 | "name": "avr-gcc", 61 | "version": "4.8.1-arduino5" 62 | }, 63 | { 64 | "packager": "arduino", 65 | "name": "avrdude", 66 | "version": "6.0.1-arduino5" 67 | } 68 | ] 69 | } 70 | ], 71 | "tools":[] 72 | } 73 | ] 74 | } -------------------------------------------------------------------------------- /platform.txt: -------------------------------------------------------------------------------- 1 | 2 | # Arduino AVR Core and platform. 3 | # ------------------------------ 4 | # 5 | # For more info: 6 | # https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5-3rd-party-Hardware-specification 7 | 8 | name=Move38 9 | version=1.1.1 10 | 11 | # AVR compile variables 12 | # --------------------- 13 | 14 | compiler.warning_flags=-w 15 | compiler.warning_flags.none=-w 16 | compiler.warning_flags.default= 17 | compiler.warning_flags.more=-Wall 18 | compiler.warning_flags.all=-Wall -Wextra 19 | 20 | # Default "compiler.path" is correct, change only if you want to override the initial value 21 | compiler.path={runtime.tools.avr-gcc.path}/bin/ 22 | compiler.c.cmd=avr-gcc 23 | compiler.c.flags=-c -g -Os {compiler.warning_flags} -std=gnu11 -ffunction-sections -fdata-sections -MMD -flto -fno-fat-lto-objects 24 | compiler.c.elf.flags={compiler.warning_flags} -Os -g -flto -mrelax -fuse-linker-plugin -Wl,--gc-sections 25 | compiler.c.elf.cmd=avr-gcc 26 | 27 | compiler.S.flags=-c -g -x assembler-with-cpp -flto -MMD 28 | 29 | compiler.cpp.cmd=avr-g++ 30 | compiler.cpp.flags=-c -g -Os {compiler.warning_flags} -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -MMD -flto 31 | 32 | compiler.ar.cmd=avr-gcc-ar 33 | compiler.ar.flags=rcs 34 | 35 | compiler.objcopy.cmd=avr-objcopy 36 | compiler.objcopy.eep.flags=-O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 37 | 38 | # We need to explicitly remove .BSS from the hex file since the linker inexplicably includes .bss in .text 39 | # when we include .ipcram in .bss. 40 | 41 | # This 0x1700 is is the physical start address of the `built-in` program image area. This is 42 | # defined in the blinkbios as `FLASH_BUILTIN_IMAGE_START_ADDRESS`. 43 | # If you change this, then you must also update the LENGTH of the TEXT 44 | # area in the MEMORY section of linkscripts/avr5.xn to match. 45 | # Finally you must also update `blink.upload.maximum_size` in boards.txt 46 | # so that the Arduino IDE reports the correct values for program size after a compile. 47 | # Also remember that AVR flash memory is 16 bits wide so this number 48 | # is 1/2 what you expect it to be if you are thinking in bytes. 49 | compiler.elf2hex.flags=--change-addresses 0x1700 -O ihex -R .eepromm 50 | compiler.elf2hex.cmd=avr-objcopy 51 | compiler.ldflags= 52 | compiler.size.cmd=avr-size 53 | 54 | # This can be overridden in boards.txt 55 | build.extra_flags= 56 | 57 | # These can be overridden in platform.local.txt 58 | compiler.c.extra_flags= 59 | compiler.c.elf.extra_flags= 60 | compiler.S.extra_flags= 61 | compiler.cpp.extra_flags= 62 | compiler.ar.extra_flags= 63 | compiler.objcopy.eep.extra_flags= 64 | compiler.elf2hex.extra_flags= 65 | 66 | # AVR compile patterns 67 | # -------------------- 68 | 69 | ## Compile c files 70 | recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.c.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.c.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" 71 | 72 | ## Compile c++ files 73 | recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.cpp.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" 74 | 75 | ## Compile S files 76 | recipe.S.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.S.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.S.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" 77 | 78 | ## Create archives 79 | # archive_file_path is needed for backwards compatibility with IDE 1.6.5 or older, IDE 1.6.6 or newer overrides this value 80 | archive_file_path={build.path}/{archive_file} 81 | recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}" 82 | 83 | ## Combine gc-sections, archives, and objects 84 | #recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} -mmcu={build.mcu} {compiler.c.elf.extra_flags} -Wl,--script={runtime.platform.path}/linkscripts/avr5.xn -Wl,-nostartfiles -o "{build.path}/{build.project_name}.elf" {object_files} "{build.path}/{archive_file}" "-L{build.path}" -lm 85 | #recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} -mmcu={build.mcu} {compiler.c.elf.extra_flags} -Wl,--print-gc-sections -Wl,--script={runtime.platform.path}/linkscripts/avr5.xn -Wl,-Map,{build.path}/out.map -nostartfiles -o "{build.path}/{build.project_name}.elf" {object_files} "{build.path}/{archive_file}" "-L{build.path}" -lm 86 | # Ok, I know that hard-coded path to the startup.S.o is ugly, but it took me a full day to figure out that the startup file can not be inside the archive and now I just need it to works so don't judge me. 87 | recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} -mmcu={build.mcu} {compiler.c.elf.extra_flags} -T "{runtime.platform.path}/linkscripts/avr5.xn" -nostartfiles -o "{build.path}/{build.project_name}.elf" {object_files} "{build.path}/{archive_file}" "-L{build.path}" -lm 88 | 89 | ## Create output files (.eep and .hex) 90 | recipe.objcopy.eep.pattern="{compiler.path}{compiler.objcopy.cmd}" {compiler.objcopy.eep.flags} {compiler.objcopy.eep.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.eep" 91 | recipe.objcopy.hex.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf2hex.flags} {compiler.elf2hex.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.hex" 92 | 93 | ## Save hex 94 | recipe.output.tmp_file={build.project_name}.hex 95 | recipe.output.save_file={build.project_name}.{build.variant}.hex 96 | 97 | ## Compute size 98 | recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf" 99 | recipe.size.regex=^(?:\.text|\.data|\.bootloader)\s+([0-9]+).* 100 | recipe.size.regex.data=^(?:\.data|\.bss|\.noinit)\s+([0-9]+).* 101 | recipe.size.regex.eeprom=^(?:\.eeprom)\s+([0-9]+).* 102 | 103 | ## Preprocessor 104 | preproc.includes.flags=-w -x c++ -M -MG -MP 105 | recipe.preproc.includes="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} {preproc.includes.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.cpp.extra_flags} {build.extra_flags} {includes} "{source_file}" 106 | 107 | preproc.macros.flags=-w -x c++ -E -CC 108 | recipe.preproc.macros="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} {preproc.macros.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.cpp.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{preprocessed_file_path}" 109 | 110 | # AVR Uploader/Programmers tools 111 | # ------------------------------ 112 | 113 | tools.avrdude.path={runtime.tools.avrdude.path} 114 | tools.avrdude.cmd.path={path}/bin/avrdude 115 | tools.avrdude.config.path={path}/etc/avrdude.conf 116 | 117 | tools.avrdude.network_cmd={runtime.tools.arduinoOTA.path}/bin/arduinoOTA 118 | 119 | tools.avrdude.upload.params.verbose=-v 120 | tools.avrdude.upload.params.quiet=-q -q 121 | # tools.avrdude.upload.verify is needed for backwards compatibility with IDE 1.6.8 or older, IDE 1.6.9 or newer overrides this value 122 | tools.avrdude.upload.verify= 123 | tools.avrdude.upload.params.noverify=-V 124 | 125 | # We replace the upload pattern with the program pattern because for now blinks code comes via programmer, 126 | # so putting this here lets us push the convenient "Upload" button rather than having to do the "Via Programmer" menu pick. 127 | # The -B 5 speeds up the clock to 200KHz which is the fastest we can go with the currently programmed 1MHz MCU clock at startup 128 | #Note that this used to be set to 250KHz but I found two different blinks that would not program at this speed 129 | 130 | # The second -U:flash programs the BlinkBIOS image into the bootlader are of the flash (check out the BlinkBIOS project for more info) 131 | # The -U:efuse programs the extended fuse to enable BOOTRST. This makes the chip jump to the bootloader area (with BlinkBIOS) on reset rather than 0x0000 132 | # The -u means "don't change the fuses back to what they were when we started". Silly, yes. 133 | # The -cusbtiny is hardcoded in there becuase the {protocol} does not seem to work with the upload event 134 | tools.avrdude.upload.pattern="{cmd.path}" "-C{config.path}" -B 5 {upload.verbose} {upload.verify} -p{build.mcu} -cusbtiny "-Uflash:w:{build.path}/{build.project_name}.hex:i" "-Uflash:w:{runtime.platform.path}/bootloaders/BlinkBIOS.hex:i" "-Uefuse:w:0xf8:m" -u 135 | #tools.avrdude.upload.pattern="{cmd.path}" "-C{config.path}" {upload.verbose} {upload.verify} -p{build.mcu} -c{upload.protocol} "-P{serial.port}" -b{upload.speed} -D "-Uflash:w:{build.path}/{build.project_name}.hex:i" "-Uflash:w:{build.core}/bootloader/XXXbin/blinkboot.hex:i" 136 | 137 | tools.avrdude.program.params.verbose=-v 138 | tools.avrdude.program.params.quiet=-q -q 139 | # tools.avrdude.program.verify is needed for backwards compatibility with IDE 1.6.8 or older, IDE 1.6.9 or newer overrides this value 140 | tools.avrdude.program.verify= 141 | tools.avrdude.program.params.noverify=-V 142 | 143 | # This just makes the "Upload via programmer" menu option work and do the same thing as the Upload button 144 | # The -B 5 speeds up the clock to 200KHz which is the fastest we can go with the currently programmed 1MHz MCU clock at startup 145 | #Note that this used to be set to 250KHz but I found two different blinks that would not program at this speed 146 | tools.avrdude.program.pattern="{cmd.path}" "-C{config.path}" -B 5 {program.verbose} {program.verify} -p{build.mcu} -c{protocol} {program.extra_params} "-Uflash:w:{build.path}/{build.project_name}.hex:i" "-Uflash:w:{runtime.platform.path}/bootloaders/BlinkBIOS.hex:i" -u 147 | 148 | tools.avrdude.erase.params.verbose=-v 149 | tools.avrdude.erase.params.quiet=-q -q 150 | tools.avrdude.erase.pattern="{cmd.path}" "-C{config.path}" {erase.verbose} -p{build.mcu} -c{protocol} {program.extra_params} -e -Ulock:w:{bootloader.unlock_bits}:m -Uefuse:w:{bootloader.extended_fuses}:m -Uhfuse:w:{bootloader.high_fuses}:m -Ulfuse:w:{bootloader.low_fuses}:m 151 | 152 | tools.avrdude.bootloader.params.verbose=-v 153 | tools.avrdude.bootloader.params.quiet=-q -q 154 | tools.avrdude.bootloader.pattern="{cmd.path}" "-C{config.path}" {bootloader.verbose} -p{build.mcu} -c{protocol} {program.extra_params} "-Uflash:w:{runtime.platform.path}/bootloaders/BlinkBIOS.hex:i" "-Uefuse:w:0xf8:m" -u 155 | 156 | tools.avrdude_remote.upload.pattern=/usr/bin/run-avrdude /tmp/sketch.hex {upload.verbose} -p{build.mcu} 157 | 158 | tools.avrdude.upload.network_pattern="{network_cmd}" -address {serial.port} -port {upload.network.port} -sketch "{build.path}/{build.project_name}.hex" -upload {upload.network.endpoint_upload} -sync {upload.network.endpoint_sync} -reset {upload.network.endpoint_reset} -sync_exp {upload.network.sync_return} 159 | 160 | # USB Default Flags 161 | # Default blank usb manufacturer will be filled in at compile time 162 | # - from numeric vendor ID, set to Unknown otherwise 163 | build.usb_manufacturer="Unknown" 164 | build.usb_flags=-DUSB_VID={build.vid} -DUSB_PID={build.pid} '-DUSB_MANUFACTURER={build.usb_manufacturer}' '-DUSB_PRODUCT={build.usb_product}' 165 | -------------------------------------------------------------------------------- /programmers.txt: -------------------------------------------------------------------------------- 1 | avrisp.name=Blinks AVR ISP 2 | avrisp.communication=serial 3 | avrisp.protocol=stk500v1 4 | avrisp.program.protocol=stk500v1 5 | avrisp.program.tool=avrdude 6 | avrisp.program.extra_params=-P{serial.port} 7 | 8 | avrispmkii.name=Blinks AVRISP mkII 9 | avrispmkii.communication=usb 10 | avrispmkii.protocol=stk500v2 11 | avrispmkii.program.protocol=stk500v2 12 | avrispmkii.program.tool=avrdude 13 | avrispmkii.program.extra_params=-Pusb 14 | 15 | usbtinyisp.name=Blinks USBtinyISP 16 | usbtinyisp.protocol=usbtiny 17 | usbtinyisp.program.tool=avrdude 18 | usbtinyisp.program.extra_params= 19 | 20 | arduinoisp.name=Blinks ArduinoISP 21 | arduinoisp.protocol=arduinoisp 22 | arduinoisp.program.tool=avrdude 23 | arduinoisp.program.extra_params= 24 | 25 | 26 | usbasp.name=Blinks USBasp 27 | usbasp.communication=usb 28 | usbasp.protocol=usbasp 29 | usbasp.program.protocol=usbasp 30 | usbasp.program.tool=avrdude 31 | usbasp.program.extra_params=-Pusb 32 | 33 | arduinoasisp.name=Blinks Arduino as ISP 34 | arduinoasisp.communication=serial 35 | arduinoasisp.protocol=arduino 36 | arduinoasisp.speed=19200 37 | arduinoasisp.program.protocol=arduino 38 | arduinoasisp.program.speed=19200 39 | arduinoasisp.program.tool=avrdude 40 | arduinoasisp.program.extra_params=-P{serial.port} -b{program.speed} 41 | -------------------------------------------------------------------------------- /variants/standard/dummy.txt: -------------------------------------------------------------------------------- 1 | This file is only here so git will make this directory. --------------------------------------------------------------------------------