├── .gitignore ├── README.md ├── gps_i2c ├── .cproject ├── .project ├── .settings │ └── de.innot.avreclipse.core.prefs └── gps_i2c.c ├── i2c ├── .cproject ├── .project ├── .settings │ └── de.innot.avreclipse.core.prefs ├── i2c.c └── i2c.h ├── i2c_master_test ├── .cproject ├── .project ├── .settings │ └── de.innot.avreclipse.core.prefs └── i2c_master_test.c ├── i2c_slave_test ├── .cproject ├── .project ├── .settings │ └── de.innot.avreclipse.core.prefs └── i2c_slave_test.c ├── lcd ├── .cproject ├── .project ├── .settings │ └── de.innot.avreclipse.core.prefs ├── lcd.c └── lcd.h ├── lcd_i2c_digital_clock ├── .cproject ├── .project ├── .settings │ └── de.innot.avreclipse.core.prefs └── lcd_i2c_digital_clock.c ├── lcd_test ├── .cproject ├── .project ├── .settings │ └── de.innot.avreclipse.core.prefs └── lcd_test.c ├── led_analog_clock ├── .cproject ├── .project ├── .settings │ └── de.innot.avreclipse.core.prefs ├── Doxyfile ├── led_analog_clock.c ├── led_analog_clock_v1.c ├── led_analog_clock_v1.h ├── led_analog_clock_v2.c ├── led_analog_clock_v2.h ├── led_analog_watch_v1.c ├── led_analog_watch_v1.h ├── led_mapping.c └── led_mapping.h ├── led_charlieplex ├── .cproject ├── .project ├── .settings │ └── de.innot.avreclipse.core.prefs ├── Doxyfile ├── led_charlieplex.c └── led_charlieplex.h ├── led_sequencer ├── .cproject ├── .project ├── .settings │ └── de.innot.avreclipse.core.prefs ├── led_sequencer.c └── led_sequencer.h ├── nmea ├── .cproject ├── .project ├── .settings │ └── de.innot.avreclipse.core.prefs ├── nmea.c └── nmea.h ├── rtc ├── .cproject ├── .project ├── .settings │ └── de.innot.avreclipse.core.prefs ├── rtc.c ├── rtc.h ├── rtc_ds1307.c ├── rtc_ds1307.h └── rtc_types.h ├── rtc_test ├── .cproject ├── .project ├── .settings │ └── de.innot.avreclipse.core.prefs └── rtc_test.c ├── uart ├── .cproject ├── .project ├── .settings │ └── de.innot.avreclipse.core.prefs ├── README ├── TODO ├── uart.c ├── uart.h ├── uart_description.c ├── uart_description.h └── uart_quirks.h └── uart_test ├── .cproject ├── .project ├── .settings └── de.innot.avreclipse.core.prefs └── uart_test.c /.gitignore: -------------------------------------------------------------------------------- 1 | .metadata 2 | Debug 3 | Release 4 | Release_* 5 | RemoteSystemsTempFiles 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Jeremy Cole's AVR Projects # 2 | 3 | Many smaller projects written by Jeremy Cole on Atmel AVR MCUs: 4 | 5 | * [uart](https://github.com/jeremycole/avr/tree/master/uart) -- A UART (serial) library based on Peter Fleury's uartlibrary. Also see [uart_test](https://github.com/jeremycole/avr/tree/master/uart_test). 6 | * [i2c](https://github.com/jeremycole/avr/tree/master/i2c) -- An I2C (aka TWI) library initially based on Peter Fleury's i2cmaster. Now includes slave mode support using callback functions. Also see [i2c_master_test](https://github.com/jeremycole/avr/tree/master/i2c_master_test) and [i2c_slave_test](https://github.com/jeremycole/avr/tree/master/i2c_slave_test). 7 | * [rtc](https://github.com/jeremycole/avr/tree/master/rtc) -- A custom real-time clock (RTC) library currently supporting the Maxim's DS1307 I2C-connected RTC chip. The rtc library requires the i2c library above. Also see [rtc_test](https://github.com/jeremycole/avr/tree/master/rtc_test). 8 | * [lcd](https://github.com/jeremycole/avr/tree/master/lcd) -- An LCD library supporting both 8-bit and 4-bit parallel modes of the HD44780U LCD controller. Also see [lcd_test](https://github.com/jeremycole/avr/tree/master/lcd_test). 9 | * [led_charlieplex](https://github.com/jeremycole/avr/tree/master/led_charlieplex) -- A custom library for generically describing the structure of and controlling a charlieplexed LED matrix. 10 | * [led_sequencer](https://github.com/jeremycole/avr/tree/master/led_sequencer) -- A custom library for time-sequencing LED animations, supporting the led_charlieplex library for describing the LED matrix to play animations on. 11 | * [nmea](https://github.com/jeremycole/avr/tree/master/nmea) -- An NMEA sentence parser for interoperation with GPS devices. Currently only supports `$GPRMC` sentences. 12 | 13 | Larger specific projects: 14 | 15 | * [led_analog_clock](https://github.com/jeremycole/avr/tree/master/led_analog_clock) -- The complete set of code using the uart (for debugging and setting the time), i2c, rtc, led_charlieplex, and led_sequencer libraries. Can connect to the lcd_i2c_digital_clock via I2C interface. 16 | * [lcd_i2c_digital_clock](https://github.com/jeremycole/avr/tree/master/lcd_i2c_digital_clock) -- An LCD-based digital clock module that attaches to led_analog_clock via I2C interface and displays the time in digital form. 17 | * [gps_i2c](https://github.com/jeremycole/avr/tree/master/gps_i2c) -- A translator from UART to I2C to allow a GPS to be attached to the led_analog_clock project to provide an accurate time sync source. -------------------------------------------------------------------------------- /gps_i2c/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | gps_i2c 4 | 5 | 6 | i2c 7 | nmea 8 | rtc 9 | uart 10 | 11 | 12 | 13 | org.eclipse.cdt.managedbuilder.core.genmakebuilder 14 | clean,full,incremental, 15 | 16 | 17 | 18 | 19 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder 20 | full,incremental, 21 | 22 | 23 | 24 | 25 | 26 | org.eclipse.cdt.core.cnature 27 | org.eclipse.cdt.managedbuilder.core.managedBuildNature 28 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature 29 | de.innot.avreclipse.core.avrnature 30 | 31 | 32 | -------------------------------------------------------------------------------- /gps_i2c/.settings/de.innot.avreclipse.core.prefs: -------------------------------------------------------------------------------- 1 | avrtarget/ClockFrequency=8000000 2 | avrtarget/ExtRAMSize=0 3 | avrtarget/ExtendedRAM=false 4 | avrtarget/MCUType=atmega1284p 5 | avrtarget/UseEEPROM=false 6 | avrtarget/UseExtendedRAMforHeap=true 7 | avrtarget/de.innot.avreclipse.configuration.app.release.881431360.1697256572/ClockFrequency=8000000 8 | avrtarget/de.innot.avreclipse.configuration.app.release.881431360.1697256572/ExtRAMSize=0 9 | avrtarget/de.innot.avreclipse.configuration.app.release.881431360.1697256572/ExtendedRAM=false 10 | avrtarget/de.innot.avreclipse.configuration.app.release.881431360.1697256572/MCUType=atmega1284p 11 | avrtarget/de.innot.avreclipse.configuration.app.release.881431360.1697256572/UseEEPROM=false 12 | avrtarget/de.innot.avreclipse.configuration.app.release.881431360.1697256572/UseExtendedRAMforHeap=true 13 | avrtarget/de.innot.avreclipse.configuration.app.release.881431360.1697256572/avrdude/BitBangDelay= 14 | avrtarget/de.innot.avreclipse.configuration.app.release.881431360.1697256572/avrdude/Bitclock= 15 | avrtarget/de.innot.avreclipse.configuration.app.release.881431360.1697256572/avrdude/EEPROMFile= 16 | avrtarget/de.innot.avreclipse.configuration.app.release.881431360.1697256572/avrdude/EEPROMFromConfig=true 17 | avrtarget/de.innot.avreclipse.configuration.app.release.881431360.1697256572/avrdude/FlashFile= 18 | avrtarget/de.innot.avreclipse.configuration.app.release.881431360.1697256572/avrdude/FlashFromConfig=true 19 | avrtarget/de.innot.avreclipse.configuration.app.release.881431360.1697256572/avrdude/Fuses/ByteValues=194\:209\:253 20 | avrtarget/de.innot.avreclipse.configuration.app.release.881431360.1697256572/avrdude/Fuses/FileName= 21 | avrtarget/de.innot.avreclipse.configuration.app.release.881431360.1697256572/avrdude/Fuses/MCUid=atmega1284p 22 | avrtarget/de.innot.avreclipse.configuration.app.release.881431360.1697256572/avrdude/Fuses/UseFile=false 23 | avrtarget/de.innot.avreclipse.configuration.app.release.881431360.1697256572/avrdude/Fuses/Write=true 24 | avrtarget/de.innot.avreclipse.configuration.app.release.881431360.1697256572/avrdude/NoChipErase=false 25 | avrtarget/de.innot.avreclipse.configuration.app.release.881431360.1697256572/avrdude/NoSigCheck=false 26 | avrtarget/de.innot.avreclipse.configuration.app.release.881431360.1697256572/avrdude/NoVerify=false 27 | avrtarget/de.innot.avreclipse.configuration.app.release.881431360.1697256572/avrdude/NoWrite=false 28 | avrtarget/de.innot.avreclipse.configuration.app.release.881431360.1697256572/avrdude/OtherOptions= 29 | avrtarget/de.innot.avreclipse.configuration.app.release.881431360.1697256572/avrdude/ProgrammerID=programmerconfig.1 30 | avrtarget/de.innot.avreclipse.configuration.app.release.881431360.1697256572/avrdude/UseCounter=false 31 | avrtarget/de.innot.avreclipse.configuration.app.release.881431360.1697256572/avrdude/WriteEEPROM=false 32 | avrtarget/de.innot.avreclipse.configuration.app.release.881431360.1697256572/avrdude/WriteFlash=true 33 | avrtarget/perConfig=true 34 | eclipse.preferences.version=1 35 | -------------------------------------------------------------------------------- /i2c/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | i2c 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.cdt.managedbuilder.core.genmakebuilder 10 | clean,full,incremental, 11 | 12 | 13 | ?name? 14 | 15 | 16 | 17 | org.eclipse.cdt.make.core.append_environment 18 | true 19 | 20 | 21 | org.eclipse.cdt.make.core.autoBuildTarget 22 | all 23 | 24 | 25 | org.eclipse.cdt.make.core.buildArguments 26 | 27 | 28 | 29 | org.eclipse.cdt.make.core.buildCommand 30 | make 31 | 32 | 33 | org.eclipse.cdt.make.core.buildLocation 34 | ${workspace_loc:/i2c/Release} 35 | 36 | 37 | org.eclipse.cdt.make.core.cleanBuildTarget 38 | clean 39 | 40 | 41 | org.eclipse.cdt.make.core.contents 42 | org.eclipse.cdt.make.core.activeConfigSettings 43 | 44 | 45 | org.eclipse.cdt.make.core.enableAutoBuild 46 | false 47 | 48 | 49 | org.eclipse.cdt.make.core.enableCleanBuild 50 | true 51 | 52 | 53 | org.eclipse.cdt.make.core.enableFullBuild 54 | true 55 | 56 | 57 | org.eclipse.cdt.make.core.fullBuildTarget 58 | all 59 | 60 | 61 | org.eclipse.cdt.make.core.stopOnError 62 | true 63 | 64 | 65 | org.eclipse.cdt.make.core.useDefaultBuildCmd 66 | true 67 | 68 | 69 | 70 | 71 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder 72 | 73 | 74 | 75 | 76 | 77 | org.eclipse.cdt.core.cnature 78 | org.eclipse.cdt.managedbuilder.core.managedBuildNature 79 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature 80 | de.innot.avreclipse.core.avrnature 81 | 82 | 83 | -------------------------------------------------------------------------------- /i2c/.settings/de.innot.avreclipse.core.prefs: -------------------------------------------------------------------------------- 1 | avrtarget/ClockFrequency=8000000 2 | avrtarget/ExtRAMSize=0 3 | avrtarget/ExtendedRAM=false 4 | avrtarget/MCUType=atmega644 5 | avrtarget/UseEEPROM=false 6 | avrtarget/UseExtendedRAMforHeap=true 7 | avrtarget/avrdude/BitBangDelay= 8 | avrtarget/avrdude/Bitclock=10 9 | avrtarget/avrdude/EEPROMFile= 10 | avrtarget/avrdude/EEPROMFromConfig=true 11 | avrtarget/avrdude/FlashFile= 12 | avrtarget/avrdude/FlashFromConfig=true 13 | avrtarget/avrdude/NoChipErase=false 14 | avrtarget/avrdude/NoSigCheck=false 15 | avrtarget/avrdude/NoVerify=false 16 | avrtarget/avrdude/NoWrite=false 17 | avrtarget/avrdude/OtherOptions= 18 | avrtarget/avrdude/ProgrammerID=programmerconfig.1 19 | avrtarget/avrdude/UseCounter=false 20 | avrtarget/avrdude/WriteEEPROM=false 21 | avrtarget/avrdude/WriteFlash=true 22 | avrtarget/de.innot.avreclipse.configuration.lib.release.6991877.1692053050.931460294/ClockFrequency=8000000 23 | avrtarget/de.innot.avreclipse.configuration.lib.release.6991877.1692053050.931460294/ExtRAMSize=0 24 | avrtarget/de.innot.avreclipse.configuration.lib.release.6991877.1692053050.931460294/ExtendedRAM=false 25 | avrtarget/de.innot.avreclipse.configuration.lib.release.6991877.1692053050.931460294/MCUType=atmega1284p 26 | avrtarget/de.innot.avreclipse.configuration.lib.release.6991877.1692053050.931460294/UseEEPROM=false 27 | avrtarget/de.innot.avreclipse.configuration.lib.release.6991877.1692053050.931460294/UseExtendedRAMforHeap=true 28 | avrtarget/de.innot.avreclipse.configuration.lib.release.6991877.1692053050/ClockFrequency=8000000 29 | avrtarget/de.innot.avreclipse.configuration.lib.release.6991877.1692053050/ExtRAMSize=0 30 | avrtarget/de.innot.avreclipse.configuration.lib.release.6991877.1692053050/ExtendedRAM=false 31 | avrtarget/de.innot.avreclipse.configuration.lib.release.6991877.1692053050/MCUType=atmega644 32 | avrtarget/de.innot.avreclipse.configuration.lib.release.6991877.1692053050/UseEEPROM=false 33 | avrtarget/de.innot.avreclipse.configuration.lib.release.6991877.1692053050/UseExtendedRAMforHeap=true 34 | avrtarget/perConfig=true 35 | eclipse.preferences.version=1 36 | -------------------------------------------------------------------------------- /i2c/i2c.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Jeremy Cole 3 | Copyright (c) 2006, Peter Fleury 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | */ 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "i2c.h" 27 | 28 | /* I2C clock in Hz */ 29 | #ifndef I2C_SCL_CLOCK 30 | #define I2C_SCL_CLOCK 100000L 31 | #endif 32 | 33 | #define I2C_WAIT_CLEAR(v, b) while(!((v) & _BV((b)))) 34 | #define I2C_WAIT_SET(v, b) while((v) & _BV((b))) 35 | 36 | #define I2C_ENABLE_ISR() TWCR |= _BV(TWIE) 37 | #define I2C_DISABLE_ISR() TWCR &= ~_BV(TWIE) 38 | 39 | volatile i2c_t i2c_global; 40 | 41 | ISR(TWI_vect) 42 | { 43 | uint8_t status; 44 | i2c_mode_t last_mode; 45 | 46 | last_mode = i2c_global.mode; 47 | status = TW_STATUS; 48 | 49 | /* 50 | * Receiving any of these statuses changes the current I2C mode regardless 51 | * of its current state. 52 | */ 53 | switch(status) 54 | { 55 | case TW_ST_SLA_ACK: 56 | case TW_ST_ARB_LOST_SLA_ACK: 57 | i2c_global.mode = I2C_MODE_ST; 58 | break; 59 | case TW_SR_SLA_ACK: 60 | case TW_SR_ARB_LOST_SLA_ACK: 61 | case TW_SR_GCALL_ACK: 62 | case TW_SR_ARB_LOST_GCALL_ACK: 63 | i2c_global.mode = I2C_MODE_SR; 64 | break; 65 | case TW_SR_STOP: 66 | TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT) | _BV(TWEA); 67 | i2c_global.mode = I2C_MODE_IDLE; 68 | break; 69 | case TW_NO_INFO: 70 | case TW_BUS_ERROR: 71 | TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT) | _BV(TWEA); 72 | i2c_global.mode = I2C_MODE_IDLE; 73 | break; 74 | } 75 | 76 | switch(i2c_global.mode) 77 | { 78 | case I2C_MODE_MT: 79 | case I2C_MODE_MR: 80 | break; 81 | 82 | case I2C_MODE_ST: 83 | if(i2c_global.st_callback) 84 | { 85 | (*i2c_global.st_callback)(status, last_mode, i2c_global.mode); 86 | TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT) | _BV(TWEA); 87 | } 88 | break; 89 | case I2C_MODE_SR: 90 | if(i2c_global.sr_callback) 91 | { 92 | if(0 == (*i2c_global.sr_callback)(status, last_mode, i2c_global.mode)) 93 | TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT) | _BV(TWEA); 94 | } 95 | break; 96 | 97 | case I2C_MODE_IDLE: 98 | if(last_mode == I2C_MODE_SR) 99 | { 100 | if(i2c_global.stop_callback) 101 | { 102 | (*i2c_global.stop_callback)(status, last_mode, i2c_global.mode); 103 | } 104 | } 105 | break; 106 | case I2C_MODE_UNKNOWN: 107 | default: 108 | break; 109 | } 110 | } 111 | 112 | /* 113 | * Initialization of the I2C bus interface. Need to be called only once. 114 | */ 115 | void i2c_init(void) 116 | { 117 | TWBR = ((F_CPU/I2C_SCL_CLOCK)-16)/2; 118 | i2c_global.mode = I2C_MODE_IDLE; 119 | i2c_global.st_callback = NULL; 120 | i2c_global.sr_callback = NULL; 121 | I2C_ENABLE_ISR(); 122 | } 123 | 124 | uint8_t i2c_slave_init(uint8_t address, uint8_t address_mask, uint8_t gcall) 125 | { 126 | TWAR = address | (gcall & 0x01); 127 | TWAMR = address_mask; 128 | TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT) | _BV(TWEA); 129 | 130 | return TWAR; 131 | } 132 | 133 | /* 134 | * Issues a start condition and sends address and transfer direction. 135 | * 136 | * Return: 0 device accessible 137 | * 1 failed to access device 138 | */ 139 | uint8_t i2c_start(uint8_t address, uint8_t mode) 140 | { 141 | uint8_t twst; 142 | 143 | i2c_global.mode = (mode == I2C_WRITE)?I2C_MODE_MT:I2C_MODE_MR; 144 | 145 | /* Send START condition */ 146 | TWCR = _BV(TWINT) | _BV(TWEN) | _BV(TWSTA); 147 | 148 | /* Wait until transmission completed */ 149 | I2C_WAIT_CLEAR(TWCR, TWINT); 150 | 151 | /* Check value of TWI Status Register. */ 152 | twst = TW_STATUS; 153 | if ( (twst != TW_START) && (twst != TW_REP_START)) return twst; 154 | 155 | /* Send device address */ 156 | TWDR = address | mode; 157 | TWCR = _BV(TWINT) | _BV(TWEN); 158 | 159 | /* Wait until transmission completed and ACK/NACK has been received */ 160 | I2C_WAIT_CLEAR(TWCR, TWINT); 161 | 162 | /* Check value of TWI Status Register. */ 163 | twst = TW_STATUS; 164 | if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) return twst; 165 | 166 | return 0; 167 | } 168 | 169 | 170 | /* 171 | * Issues a repeated start condition and sends address and transfer direction. 172 | * 173 | * Input: Address and transfer direction of I2C device. 174 | * 175 | * Return: 0 device accessible 176 | * 1 failed to access device 177 | */ 178 | uint8_t i2c_rep_start(uint8_t address, uint8_t mode) 179 | { 180 | return i2c_start(address, mode); 181 | } 182 | 183 | 184 | /* 185 | * Terminates the data transfer and releases the I2C bus. 186 | */ 187 | void i2c_stop(void) 188 | { 189 | /* Send STOP condition. */ 190 | TWCR = _BV(TWINT) | _BV(TWEN) | _BV(TWSTO); 191 | 192 | /* Wait until STOP condition is executed and bus released. */ 193 | I2C_WAIT_SET(TWCR, TWSTO); 194 | 195 | i2c_global.mode = I2C_MODE_IDLE; 196 | I2C_ENABLE_ISR(); 197 | } 198 | 199 | 200 | /* 201 | * Send one byte to I2C device. 202 | * 203 | * Input: byte to be transfered 204 | * 205 | * Return: 0 write successful 206 | * 1 write failed 207 | */ 208 | uint8_t i2c_write(uint8_t data) 209 | { 210 | uint8_t twst; 211 | 212 | /* Send data to the previously addressed device */ 213 | TWDR = data; 214 | TWCR = _BV(TWINT) | _BV(TWEN); 215 | 216 | /* Wait until transmission completed */ 217 | I2C_WAIT_CLEAR(TWCR, TWINT); 218 | 219 | /* Check value of TWI Status Register. */ 220 | twst = TW_STATUS; 221 | if(twst != TW_MT_DATA_ACK) 222 | return twst; 223 | 224 | return 0; 225 | } 226 | 227 | 228 | /* 229 | * Send a string of bytes to I2C device. 230 | * 231 | * Input: byte to be transfered 232 | * 233 | * Return: 0 write successful 234 | * 1 write failed 235 | */ 236 | uint8_t i2c_write_array(uint8_t *data, uint8_t count) 237 | { 238 | while(count--) 239 | { 240 | if(i2c_write(*data++) != 0) return count; 241 | } 242 | 243 | return 0; 244 | } 245 | 246 | 247 | /* 248 | * Read one byte from the I2C device, request more data from device. 249 | * 250 | * Return: byte read from I2C device 251 | */ 252 | uint8_t i2c_read_ack(void) 253 | { 254 | TWCR = _BV(TWINT) | _BV(TWEN) | _BV(TWEA); 255 | I2C_WAIT_CLEAR(TWCR, TWINT); 256 | 257 | return TWDR; 258 | } 259 | 260 | 261 | /* 262 | * Read one byte from the I2C device, read is followed by a STOP condition 263 | * 264 | * Return: byte read from I2C device 265 | */ 266 | uint8_t i2c_read_nak(void) 267 | { 268 | TWCR = _BV(TWINT) | _BV(TWEN); 269 | I2C_WAIT_CLEAR(TWCR, TWINT); 270 | 271 | return TWDR; 272 | } 273 | 274 | 275 | /* 276 | * Read multiple bytes from the I2C device, read may be followed by a STOP 277 | * condition if nak_last is true. 278 | * 279 | * Return: zero 280 | */ 281 | uint8_t i2c_read_many(uint8_t *buffer, uint8_t count, uint8_t nak_last) 282 | { 283 | while(count--) 284 | { 285 | *buffer++ = i2c_read(!(nak_last && (count==0))); 286 | } 287 | 288 | return 0; 289 | } 290 | -------------------------------------------------------------------------------- /i2c/i2c.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Jeremy Cole 3 | Copyright (c) 2006, Peter Fleury 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | */ 20 | 21 | #ifndef I2C_H 22 | #define I2C_H 23 | 24 | #include 25 | 26 | /**@{*/ 27 | 28 | #if (__GNUC__ * 100 + __GNUC_MINOR__) < 304 29 | #error "This library requires AVR-GCC 3.4 or later, update to newer AVR-GCC compiler !" 30 | #endif 31 | 32 | #include 33 | 34 | /** defines the data direction (reading from I2C device) in i2c_start(),i2c_rep_start() */ 35 | #define I2C_READ 1 36 | 37 | /** defines the data direction (writing to I2C device) in i2c_start(),i2c_rep_start() */ 38 | #define I2C_WRITE 0 39 | 40 | /** Only the specific address will be responded to (rather than a range) */ 41 | #define I2C_ADDRESS_MASK_SINGLE 0 42 | 43 | /** Disable responses on the general call address. */ 44 | #define I2C_GCALL_DISABLED 0 45 | 46 | /** Enable responses on the general call address. */ 47 | #define I2C_GCALL_ENABLED 1 48 | 49 | typedef enum _i2c_mode_t 50 | { 51 | I2C_MODE_UNKNOWN = 0, 52 | I2C_MODE_IDLE, 53 | I2C_MODE_MT, 54 | I2C_MODE_MR, 55 | I2C_MODE_ST, 56 | I2C_MODE_SR 57 | } i2c_mode_t; 58 | 59 | typedef uint8_t (i2c_callback_t)(uint8_t status, i2c_mode_t last_mode, i2c_mode_t current_mode); 60 | 61 | typedef struct _i2c_t 62 | { 63 | i2c_mode_t mode; 64 | i2c_callback_t *st_callback; 65 | i2c_callback_t *sr_callback; 66 | i2c_callback_t *stop_callback; 67 | } i2c_t; 68 | 69 | extern volatile i2c_t i2c_global; 70 | 71 | /** 72 | @brief initialize the I2C master interace. Need to be called only once 73 | @param void 74 | @return none 75 | */ 76 | extern void i2c_init(void); 77 | 78 | extern uint8_t i2c_slave_init(uint8_t address, uint8_t address_mask, uint8_t gcall); 79 | 80 | /** 81 | @brief Terminates the data transfer and releases the I2C bus 82 | @param void 83 | @return none 84 | */ 85 | extern void i2c_stop(void); 86 | 87 | 88 | /** 89 | @brief Issues a start condition and sends address and transfer direction 90 | 91 | @param addr address and transfer direction of I2C device 92 | @retval 0 device accessible 93 | @retval 1 failed to access device 94 | */ 95 | extern uint8_t i2c_start(uint8_t address, uint8_t mode); 96 | 97 | 98 | /** 99 | @brief Issues a repeated start condition and sends address and transfer direction 100 | 101 | @param addr address and transfer direction of I2C device 102 | @retval 0 device accessible 103 | @retval 1 failed to access device 104 | */ 105 | extern uint8_t i2c_rep_start(uint8_t address, uint8_t mode); 106 | 107 | 108 | /** 109 | @brief Issues a start condition and sends address and transfer direction 110 | 111 | If device is busy, use ack polling to wait until device ready 112 | @param addr address and transfer direction of I2C device 113 | @return none 114 | */ 115 | extern void i2c_start_wait(uint8_t address, uint8_t mode); 116 | 117 | 118 | /** 119 | @brief Send one byte to I2C device 120 | @param data byte to be transfered 121 | @retval 0 write successful 122 | @retval 1 write failed 123 | */ 124 | extern uint8_t i2c_write(uint8_t data); 125 | 126 | extern uint8_t i2c_write_array(uint8_t *data, uint8_t count); 127 | 128 | /** 129 | @brief read one byte from the I2C device, request more data from device 130 | @return byte read from I2C device 131 | */ 132 | extern uint8_t i2c_read_ack(void); 133 | 134 | /** 135 | @brief read one byte from the I2C device, read is followed by a stop condition 136 | @return byte read from I2C device 137 | */ 138 | extern uint8_t i2c_read_nak(void); 139 | 140 | /** 141 | @brief read one byte from the I2C device 142 | 143 | Implemented as a macro, which calls either i2c_read_ack or i2c_read_nak 144 | 145 | @param ack 1 send ack, request more data from device
146 | 0 send nak, read is followed by a stop condition 147 | @return byte read from I2C device 148 | */ 149 | extern uint8_t i2c_read(uint8_t ack); 150 | #define i2c_read(ack) ((ack) ? i2c_read_ack() : i2c_read_nak()) 151 | 152 | extern uint8_t i2c_read_many(uint8_t *buffer, uint8_t count, uint8_t nak_last); 153 | 154 | /**@}*/ 155 | #endif 156 | -------------------------------------------------------------------------------- /i2c_master_test/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | i2c_master_test 4 | 5 | 6 | i2c 7 | uart 8 | 9 | 10 | 11 | org.eclipse.cdt.managedbuilder.core.genmakebuilder 12 | clean,full,incremental, 13 | 14 | 15 | ?name? 16 | 17 | 18 | 19 | org.eclipse.cdt.make.core.append_environment 20 | true 21 | 22 | 23 | org.eclipse.cdt.make.core.autoBuildTarget 24 | all 25 | 26 | 27 | org.eclipse.cdt.make.core.buildArguments 28 | 29 | 30 | 31 | org.eclipse.cdt.make.core.buildCommand 32 | make 33 | 34 | 35 | org.eclipse.cdt.make.core.buildLocation 36 | ${workspace_loc:/i2c_master_test/Release} 37 | 38 | 39 | org.eclipse.cdt.make.core.cleanBuildTarget 40 | clean 41 | 42 | 43 | org.eclipse.cdt.make.core.contents 44 | org.eclipse.cdt.make.core.activeConfigSettings 45 | 46 | 47 | org.eclipse.cdt.make.core.enableAutoBuild 48 | false 49 | 50 | 51 | org.eclipse.cdt.make.core.enableCleanBuild 52 | true 53 | 54 | 55 | org.eclipse.cdt.make.core.enableFullBuild 56 | true 57 | 58 | 59 | org.eclipse.cdt.make.core.fullBuildTarget 60 | all 61 | 62 | 63 | org.eclipse.cdt.make.core.stopOnError 64 | true 65 | 66 | 67 | org.eclipse.cdt.make.core.useDefaultBuildCmd 68 | true 69 | 70 | 71 | 72 | 73 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder 74 | 75 | 76 | 77 | 78 | 79 | org.eclipse.cdt.core.cnature 80 | org.eclipse.cdt.managedbuilder.core.managedBuildNature 81 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature 82 | de.innot.avreclipse.core.avrnature 83 | 84 | 85 | -------------------------------------------------------------------------------- /i2c_master_test/.settings/de.innot.avreclipse.core.prefs: -------------------------------------------------------------------------------- 1 | #Sun Aug 15 19:00:16 PDT 2010 2 | avrtarget/ClockFrequency=8000000 3 | avrtarget/ExtRAMSize=0 4 | avrtarget/ExtendedRAM=false 5 | avrtarget/MCUType=atmega644p 6 | avrtarget/UseEEPROM=false 7 | avrtarget/UseExtendedRAMforHeap=true 8 | avrtarget/avrdude/BitBangDelay= 9 | avrtarget/avrdude/Bitclock= 10 | avrtarget/avrdude/EEPROMFile= 11 | avrtarget/avrdude/EEPROMFromConfig=true 12 | avrtarget/avrdude/FlashFile= 13 | avrtarget/avrdude/FlashFromConfig=true 14 | avrtarget/avrdude/NoChipErase=false 15 | avrtarget/avrdude/NoSigCheck=false 16 | avrtarget/avrdude/NoVerify=false 17 | avrtarget/avrdude/NoWrite=false 18 | avrtarget/avrdude/OtherOptions= 19 | avrtarget/avrdude/ProgrammerID=programmerconfig.1 20 | avrtarget/avrdude/UseCounter=false 21 | avrtarget/avrdude/WriteEEPROM=false 22 | avrtarget/avrdude/WriteFlash=true 23 | avrtarget/perConfig=false 24 | eclipse.preferences.version=1 25 | -------------------------------------------------------------------------------- /i2c_master_test/i2c_master_test.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Jeremy Cole 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program 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. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include 30 | #include 31 | 32 | int main(void) 33 | { 34 | uart_t *u0; 35 | uint8_t x = 0; 36 | 37 | _delay_ms(1000); 38 | 39 | u0 = uart_init("0", 0); 40 | uart_init_stdout(u0); 41 | 42 | i2c_init(); 43 | 44 | DDRC = _BV(PC0) | _BV(PC1); 45 | PORTC = _BV(PC0) | _BV(PC1); 46 | 47 | sei(); 48 | 49 | printf("\n\nBooted up!\n"); 50 | 51 | while(1) 52 | { 53 | printf("I2C Mode: %i\n", i2c_global.mode); 54 | if(0 == i2c_start(0x70, I2C_WRITE)) 55 | { 56 | i2c_write(x++); 57 | i2c_write(x++); 58 | i2c_write(x++); 59 | } 60 | i2c_stop(); 61 | 62 | _delay_ms(1000); 63 | } 64 | 65 | return(0); 66 | } 67 | -------------------------------------------------------------------------------- /i2c_slave_test/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | i2c_slave_test 4 | 5 | 6 | i2c 7 | uart 8 | 9 | 10 | 11 | org.eclipse.cdt.managedbuilder.core.genmakebuilder 12 | clean,full,incremental, 13 | 14 | 15 | ?name? 16 | 17 | 18 | 19 | org.eclipse.cdt.make.core.append_environment 20 | true 21 | 22 | 23 | org.eclipse.cdt.make.core.autoBuildTarget 24 | all 25 | 26 | 27 | org.eclipse.cdt.make.core.buildArguments 28 | 29 | 30 | 31 | org.eclipse.cdt.make.core.buildCommand 32 | make 33 | 34 | 35 | org.eclipse.cdt.make.core.buildLocation 36 | ${workspace_loc:/i2c_slave_test/Release} 37 | 38 | 39 | org.eclipse.cdt.make.core.cleanBuildTarget 40 | clean 41 | 42 | 43 | org.eclipse.cdt.make.core.contents 44 | org.eclipse.cdt.make.core.activeConfigSettings 45 | 46 | 47 | org.eclipse.cdt.make.core.enableAutoBuild 48 | false 49 | 50 | 51 | org.eclipse.cdt.make.core.enableCleanBuild 52 | true 53 | 54 | 55 | org.eclipse.cdt.make.core.enableFullBuild 56 | true 57 | 58 | 59 | org.eclipse.cdt.make.core.fullBuildTarget 60 | all 61 | 62 | 63 | org.eclipse.cdt.make.core.stopOnError 64 | true 65 | 66 | 67 | org.eclipse.cdt.make.core.useDefaultBuildCmd 68 | true 69 | 70 | 71 | 72 | 73 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder 74 | 75 | 76 | 77 | 78 | 79 | org.eclipse.cdt.core.cnature 80 | org.eclipse.cdt.managedbuilder.core.managedBuildNature 81 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature 82 | de.innot.avreclipse.core.avrnature 83 | 84 | 85 | -------------------------------------------------------------------------------- /i2c_slave_test/.settings/de.innot.avreclipse.core.prefs: -------------------------------------------------------------------------------- 1 | #Sun Aug 15 19:04:40 PDT 2010 2 | avrtarget/ClockFrequency=8000000 3 | avrtarget/ExtRAMSize=0 4 | avrtarget/ExtendedRAM=false 5 | avrtarget/MCUType=atmega644 6 | avrtarget/UseEEPROM=false 7 | avrtarget/UseExtendedRAMforHeap=true 8 | avrtarget/avrdude/BitBangDelay= 9 | avrtarget/avrdude/Bitclock= 10 | avrtarget/avrdude/EEPROMFile= 11 | avrtarget/avrdude/EEPROMFromConfig=true 12 | avrtarget/avrdude/FlashFile= 13 | avrtarget/avrdude/FlashFromConfig=true 14 | avrtarget/avrdude/NoChipErase=false 15 | avrtarget/avrdude/NoSigCheck=false 16 | avrtarget/avrdude/NoVerify=false 17 | avrtarget/avrdude/NoWrite=false 18 | avrtarget/avrdude/OtherOptions= 19 | avrtarget/avrdude/ProgrammerID=programmerconfig.1 20 | avrtarget/avrdude/UseCounter=false 21 | avrtarget/avrdude/WriteEEPROM=false 22 | avrtarget/avrdude/WriteFlash=true 23 | avrtarget/perConfig=false 24 | eclipse.preferences.version=1 25 | -------------------------------------------------------------------------------- /i2c_slave_test/i2c_slave_test.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Jeremy Cole 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program 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. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include 30 | #include 31 | 32 | uint8_t i2c_data[16]; 33 | uint8_t data_offset; 34 | 35 | uint8_t handle_sr(uint8_t status, i2c_mode_t last_mode, i2c_mode_t current_mode) 36 | { 37 | if(last_mode != current_mode) 38 | { 39 | data_offset=0; 40 | memset(i2c_data, 0, 16); 41 | } 42 | 43 | if(status == TW_SR_DATA_ACK || status == TW_SR_DATA_NACK) 44 | i2c_data[data_offset++] = TWDR; 45 | 46 | TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT) | _BV(TWEA); 47 | return 0; 48 | } 49 | 50 | int main(void) 51 | { 52 | uart_t *u0; 53 | 54 | _delay_ms(1000); 55 | 56 | u0 = uart_init("0", 0); 57 | uart_init_stdout(u0); 58 | 59 | i2c_init(); 60 | i2c_slave_init(0x70, 0, 0); 61 | i2c_global.sr_callback = handle_sr; 62 | 63 | sei(); 64 | 65 | printf("\n\nBooted up!\n"); 66 | 67 | while(1) 68 | { 69 | printf("I2C Mode: %i, Data: %i, %i, %i\n", i2c_global.mode, 70 | i2c_data[0], i2c_data[1], i2c_data[2]); 71 | 72 | _delay_ms(1000); 73 | } 74 | 75 | return(0); 76 | } 77 | -------------------------------------------------------------------------------- /lcd/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | lcd 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.cdt.managedbuilder.core.genmakebuilder 10 | clean,full,incremental, 11 | 12 | 13 | ?name? 14 | 15 | 16 | 17 | org.eclipse.cdt.make.core.append_environment 18 | true 19 | 20 | 21 | org.eclipse.cdt.make.core.autoBuildTarget 22 | all 23 | 24 | 25 | org.eclipse.cdt.make.core.buildArguments 26 | 27 | 28 | 29 | org.eclipse.cdt.make.core.buildCommand 30 | make 31 | 32 | 33 | org.eclipse.cdt.make.core.buildLocation 34 | ${workspace_loc:/lcd/Debug} 35 | 36 | 37 | org.eclipse.cdt.make.core.cleanBuildTarget 38 | clean 39 | 40 | 41 | org.eclipse.cdt.make.core.contents 42 | org.eclipse.cdt.make.core.activeConfigSettings 43 | 44 | 45 | org.eclipse.cdt.make.core.enableAutoBuild 46 | false 47 | 48 | 49 | org.eclipse.cdt.make.core.enableCleanBuild 50 | true 51 | 52 | 53 | org.eclipse.cdt.make.core.enableFullBuild 54 | true 55 | 56 | 57 | org.eclipse.cdt.make.core.fullBuildTarget 58 | all 59 | 60 | 61 | org.eclipse.cdt.make.core.stopOnError 62 | true 63 | 64 | 65 | org.eclipse.cdt.make.core.useDefaultBuildCmd 66 | true 67 | 68 | 69 | 70 | 71 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder 72 | 73 | 74 | 75 | 76 | 77 | org.eclipse.cdt.core.cnature 78 | org.eclipse.cdt.managedbuilder.core.managedBuildNature 79 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature 80 | de.innot.avreclipse.core.avrnature 81 | 82 | 83 | -------------------------------------------------------------------------------- /lcd/.settings/de.innot.avreclipse.core.prefs: -------------------------------------------------------------------------------- 1 | avrtarget/ClockFrequency=8000000 2 | avrtarget/ExtRAMSize=0 3 | avrtarget/ExtendedRAM=false 4 | avrtarget/MCUType=atmega644 5 | avrtarget/UseEEPROM=false 6 | avrtarget/UseExtendedRAMforHeap=true 7 | avrtarget/de.innot.avreclipse.configuration.lib.release.1970224268.527364214.727203139/ClockFrequency=8000000 8 | avrtarget/de.innot.avreclipse.configuration.lib.release.1970224268.527364214.727203139/ExtRAMSize=0 9 | avrtarget/de.innot.avreclipse.configuration.lib.release.1970224268.527364214.727203139/ExtendedRAM=false 10 | avrtarget/de.innot.avreclipse.configuration.lib.release.1970224268.527364214.727203139/MCUType=atmega1284p 11 | avrtarget/de.innot.avreclipse.configuration.lib.release.1970224268.527364214.727203139/UseEEPROM=false 12 | avrtarget/de.innot.avreclipse.configuration.lib.release.1970224268.527364214.727203139/UseExtendedRAMforHeap=true 13 | avrtarget/de.innot.avreclipse.configuration.lib.release.1970224268.527364214/ClockFrequency=8000000 14 | avrtarget/de.innot.avreclipse.configuration.lib.release.1970224268.527364214/ExtRAMSize=0 15 | avrtarget/de.innot.avreclipse.configuration.lib.release.1970224268.527364214/ExtendedRAM=false 16 | avrtarget/de.innot.avreclipse.configuration.lib.release.1970224268.527364214/MCUType=atmega644 17 | avrtarget/de.innot.avreclipse.configuration.lib.release.1970224268.527364214/UseEEPROM=false 18 | avrtarget/de.innot.avreclipse.configuration.lib.release.1970224268.527364214/UseExtendedRAMforHeap=true 19 | avrtarget/perConfig=true 20 | eclipse.preferences.version=1 21 | -------------------------------------------------------------------------------- /lcd/lcd.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Jeremy Cole 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program 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. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "lcd.h" 27 | 28 | void lcd_init(lcd_t *lcd) 29 | { 30 | *lcd->rs.ddr |= _BV(lcd->rs.bv); 31 | *lcd->rw.ddr |= _BV(lcd->rw.bv); 32 | *lcd->e.ddr |= _BV(lcd->e.bv); 33 | 34 | _delay_ms(20); 35 | lcd_parameters(lcd, lcd->interface); 36 | 37 | _delay_ms(6); 38 | lcd_parameters(lcd, lcd->interface); 39 | 40 | _delay_us(150); 41 | lcd_parameters(lcd, lcd->interface); 42 | 43 | lcd_parameters(lcd, lcd->interface | LCD_LINES_2 | LCD_FONT_5X8); 44 | lcd_entry_mode(lcd, LCD_CURSOR_INCREMENT | LCD_DISPLAY_SHIFT_OFF); 45 | lcd_clear(lcd); 46 | lcd_display_mode(lcd, LCD_DISPLAY_ON); 47 | } 48 | 49 | uint8_t _lcd_read_data(lcd_t *lcd) 50 | { 51 | uint8_t data = 0; 52 | 53 | *lcd->e.port |= _BV(lcd->e.bv); 54 | _delay_us(0.1); 55 | switch(lcd->interface) 56 | { 57 | case LCD_INTERFACE_8BIT: 58 | data = *lcd->data.pin; 59 | break; 60 | case LCD_INTERFACE_4BIT: 61 | data = ((*lcd->data.pin & (0x0f << lcd->data.bv)) >> lcd->data.bv) << 4; 62 | _delay_us(0.3); 63 | *lcd->e.port &= ~_BV(lcd->e.bv); 64 | _delay_us(0.3); 65 | *lcd->e.port |= _BV(lcd->e.bv); 66 | _delay_us(0.3); 67 | data |= ((*lcd->data.pin & (0x0f << lcd->data.bv)) >> lcd->data.bv); 68 | break; 69 | } 70 | _delay_us(0.3); 71 | *lcd->e.port &= ~_BV(lcd->e.bv); 72 | _delay_us(0.3); 73 | 74 | switch(lcd->interface) 75 | { 76 | case LCD_INTERFACE_8BIT: 77 | *lcd->data.port = 0x00; 78 | *lcd->data.ddr = 0x00; 79 | break; 80 | case LCD_INTERFACE_4BIT: 81 | *lcd->data.port &= ~(0x0f << lcd->data.bv); 82 | *lcd->data.ddr &= ~(0x0f << lcd->data.bv); 83 | break; 84 | } 85 | 86 | return data; 87 | } 88 | 89 | void _lcd_write_data(lcd_t *lcd, uint8_t data) 90 | { 91 | *lcd->e.port |= _BV(lcd->e.bv); 92 | _delay_us(0.1); 93 | switch(lcd->interface) 94 | { 95 | case LCD_INTERFACE_8BIT: 96 | *lcd->data.ddr = 0xff; 97 | *lcd->data.port = data; 98 | break; 99 | case LCD_INTERFACE_4BIT: 100 | *lcd->data.ddr |= 0x0f << lcd->data.bv; 101 | *lcd->data.port |= ((data & 0xf0) >> 4) << lcd->data.bv; 102 | _delay_us(0.3); 103 | *lcd->e.port &= ~_BV(lcd->e.bv); 104 | *lcd->data.port &= ~(0x0f << lcd->data.bv); 105 | _delay_us(0.3); 106 | *lcd->e.port |= _BV(lcd->e.bv); 107 | _delay_us(0.3); 108 | *lcd->data.port |= (data & 0x0f) << lcd->data.bv; 109 | break; 110 | } 111 | _delay_us(0.3); 112 | *lcd->e.port &= ~_BV(lcd->e.bv); 113 | _delay_us(0.3); 114 | 115 | switch(lcd->interface) 116 | { 117 | case LCD_INTERFACE_8BIT: 118 | *lcd->data.port = 0x00; 119 | *lcd->data.ddr = 0x00; 120 | break; 121 | case LCD_INTERFACE_4BIT: 122 | *lcd->data.port &= ~(0x0f << lcd->data.bv); 123 | *lcd->data.ddr &= ~(0x0f << lcd->data.bv); 124 | break; 125 | } 126 | } 127 | 128 | uint8_t lcd_read_sr(lcd_t *lcd) 129 | { 130 | int status; 131 | 132 | *lcd->rw.port |= _BV(lcd->rw.bv); 133 | *lcd->rs.port &= ~_BV(lcd->rs.bv); 134 | _delay_us(0.1); 135 | status = _lcd_read_data(lcd); 136 | *lcd->rs.port &= ~_BV(lcd->rs.bv); 137 | *lcd->rw.port &= ~_BV(lcd->rw.bv); 138 | _delay_us(0.2); 139 | 140 | return status; 141 | } 142 | 143 | void lcd_write_ir(lcd_t *lcd, uint8_t instruction) 144 | { 145 | while ((lcd_read_sr(lcd) & LCD_BUSY) != 0) {}; 146 | 147 | *lcd->rs.port &= ~_BV(lcd->rs.bv); 148 | *lcd->rw.port &= ~_BV(lcd->rw.bv); 149 | _delay_us(0.1); 150 | _lcd_write_data(lcd, instruction); 151 | _delay_us(0.2); 152 | } 153 | 154 | void lcd_write_dr(lcd_t *lcd, uint8_t data) 155 | { 156 | while ((lcd_read_sr(lcd) & LCD_BUSY) != 0) {}; 157 | 158 | *lcd->rw.port &= ~_BV(lcd->rw.bv); 159 | *lcd->rs.port |= _BV(lcd->rs.bv); 160 | _delay_us(0.1); 161 | _lcd_write_data(lcd, data); 162 | *lcd->rs.port &= ~_BV(lcd->rs.bv); 163 | *lcd->rw.port &= ~_BV(lcd->rw.bv); 164 | _delay_us(0.2); 165 | } 166 | 167 | void lcd_display_mode(lcd_t *lcd, uint8_t mode) 168 | { 169 | lcd_write_ir(lcd, LCD_IR_MODE_DISPLAY | mode); 170 | } 171 | 172 | void lcd_parameters(lcd_t *lcd, uint8_t parameters) 173 | { 174 | lcd_write_ir(lcd, LCD_IR_MODE_PARAMETERS | parameters); 175 | } 176 | 177 | void lcd_entry_mode(lcd_t *lcd, uint8_t mode) 178 | { 179 | lcd_write_ir(lcd, LCD_IR_MODE_ENTRY | mode); 180 | } 181 | 182 | void lcd_move_cursor(lcd_t *lcd, uint8_t line, uint8_t col) 183 | { 184 | lcd_write_ir(lcd, LCD_IR_MODE_DDRAM_ADDR | ((LCD_LINE_DDRAM_WIDTH * line) + col) ); 185 | } 186 | 187 | void lcd_cg_define(lcd_t *lcd, uint8_t character, uint8_t data[8]) 188 | { 189 | uint8_t pos; 190 | lcd_write_ir(lcd, LCD_IR_MODE_CGRAM_ADDR | (character * 8)); 191 | for(pos=0; pos < 8; pos++) 192 | { 193 | lcd_write_dr(lcd, data[pos]); 194 | } 195 | } 196 | 197 | void lcd_clear(lcd_t *lcd) 198 | { 199 | lcd_write_ir(lcd, LCD_IR_CLEAR); 200 | } 201 | 202 | void lcd_return_home(lcd_t *lcd) 203 | { 204 | lcd_write_ir(lcd, LCD_IR_RETURN_HOME); 205 | } 206 | 207 | void lcd_write_char(lcd_t *lcd, char c) 208 | { 209 | lcd_write_dr(lcd, c); 210 | } 211 | 212 | void lcd_write_string(lcd_t *lcd, char *s, int n) 213 | { 214 | for (; n>0; n--, s++) 215 | { 216 | lcd_write_dr(lcd, *s); 217 | } 218 | } 219 | -------------------------------------------------------------------------------- /lcd/lcd.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Jeremy Cole 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program 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. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | */ 19 | 20 | #ifndef LCD_H 21 | #define LCD_H 22 | 23 | #include 24 | 25 | #define LCD_IR_CLEAR (0x01) 26 | #define LCD_IR_RETURN_HOME (0x02) 27 | 28 | #define LCD_IR_MODE_ENTRY (0x04) 29 | #define LCD_CURSOR_DECREMENT (0x00) 30 | #define LCD_CURSOR_INCREMENT (0x02) 31 | #define LCD_DISPLAY_SHIFT_OFF (0x00) 32 | #define LCD_DISPLAY_SHIFT_ON (0x01) 33 | 34 | #define LCD_IR_MODE_DISPLAY (0x08) 35 | #define LCD_DISPLAY_ON (0x04) 36 | #define LCD_CURSOR_ON (0x02) 37 | #define LCD_CURSOR_BLINK (0x01) 38 | 39 | #define LCD_IR_MODE_PARAMETERS (0x20) 40 | #define LCD_INTERFACE_4BIT (0x00) 41 | #define LCD_INTERFACE_8BIT (0x10) 42 | #define LCD_LINES_1 (0x00) 43 | #define LCD_LINES_2 (0x08) 44 | #define LCD_FONT_5X8 (0x00) 45 | #define LCD_FONT_5X11 (0x04) 46 | 47 | #define LCD_IR_MODE_CGRAM_ADDR (0x40) 48 | #define LCD_IR_MODE_DDRAM_ADDR (0x80) 49 | 50 | #define LCD_BUSY (0x80) 51 | 52 | #define LCD_LINE_DDRAM_WIDTH (0x40) 53 | 54 | typedef struct _lcd_port_t 55 | { 56 | volatile uint8_t *pin; 57 | volatile uint8_t *port; 58 | volatile uint8_t *ddr; 59 | uint8_t bv; 60 | } lcd_port_t; 61 | 62 | typedef struct _lcd_t 63 | { 64 | uint8_t interface; 65 | lcd_port_t data; 66 | lcd_port_t rs; 67 | lcd_port_t rw; 68 | lcd_port_t e; 69 | } lcd_t; 70 | 71 | typedef uint8_t lcd_cg_t[8]; 72 | 73 | void lcd_init(lcd_t *lcd); 74 | uint8_t lcd_read_sr(lcd_t *lcd); 75 | void lcd_write_ir(lcd_t *lcd, uint8_t instruction); 76 | void lcd_write_dr(lcd_t *lcd, uint8_t data); 77 | void lcd_display_mode(lcd_t *lcd, uint8_t mode); 78 | void lcd_parameters(lcd_t *lcd, uint8_t parameters); 79 | void lcd_entry_mode(lcd_t *lcd, uint8_t mode); 80 | void lcd_move_cursor(lcd_t *lcd, uint8_t line, uint8_t col); 81 | void lcd_cg_define(lcd_t *lcd, uint8_t character, uint8_t data[8]); 82 | void lcd_clear(lcd_t *lcd); 83 | void lcd_return_home(lcd_t *lcd); 84 | void lcd_write_char(lcd_t *lcd, char c); 85 | void lcd_write_string(lcd_t *lcd, char *s, int n); 86 | 87 | #endif /* LCD_H */ 88 | -------------------------------------------------------------------------------- /lcd_i2c_digital_clock/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | lcd_i2c_digital_clock 4 | 5 | 6 | i2c 7 | lcd 8 | rtc 9 | uart 10 | 11 | 12 | 13 | org.eclipse.cdt.managedbuilder.core.genmakebuilder 14 | clean,full,incremental, 15 | 16 | 17 | ?name? 18 | 19 | 20 | 21 | org.eclipse.cdt.make.core.append_environment 22 | true 23 | 24 | 25 | org.eclipse.cdt.make.core.autoBuildTarget 26 | all 27 | 28 | 29 | org.eclipse.cdt.make.core.buildArguments 30 | 31 | 32 | 33 | org.eclipse.cdt.make.core.buildCommand 34 | make 35 | 36 | 37 | org.eclipse.cdt.make.core.buildLocation 38 | ${workspace_loc:/lcd_test/Release} 39 | 40 | 41 | org.eclipse.cdt.make.core.cleanBuildTarget 42 | clean 43 | 44 | 45 | org.eclipse.cdt.make.core.contents 46 | org.eclipse.cdt.make.core.activeConfigSettings 47 | 48 | 49 | org.eclipse.cdt.make.core.enableAutoBuild 50 | false 51 | 52 | 53 | org.eclipse.cdt.make.core.enableCleanBuild 54 | true 55 | 56 | 57 | org.eclipse.cdt.make.core.enableFullBuild 58 | true 59 | 60 | 61 | org.eclipse.cdt.make.core.fullBuildTarget 62 | all 63 | 64 | 65 | org.eclipse.cdt.make.core.stopOnError 66 | true 67 | 68 | 69 | org.eclipse.cdt.make.core.useDefaultBuildCmd 70 | true 71 | 72 | 73 | 74 | 75 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder 76 | 77 | 78 | 79 | 80 | 81 | org.eclipse.cdt.core.cnature 82 | org.eclipse.cdt.managedbuilder.core.managedBuildNature 83 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature 84 | de.innot.avreclipse.core.avrnature 85 | 86 | 87 | -------------------------------------------------------------------------------- /lcd_i2c_digital_clock/.settings/de.innot.avreclipse.core.prefs: -------------------------------------------------------------------------------- 1 | avrtarget/ClockFrequency=8000000 2 | avrtarget/ExtRAMSize=0 3 | avrtarget/ExtendedRAM=false 4 | avrtarget/MCUType=atmega644 5 | avrtarget/UseEEPROM=false 6 | avrtarget/UseExtendedRAMforHeap=true 7 | avrtarget/avrdude/BitBangDelay= 8 | avrtarget/avrdude/Bitclock=10 9 | avrtarget/avrdude/EEPROMFile= 10 | avrtarget/avrdude/EEPROMFromConfig=true 11 | avrtarget/avrdude/FlashFile= 12 | avrtarget/avrdude/FlashFromConfig=true 13 | avrtarget/avrdude/Fuses/ByteValues=194\:217\:255 14 | avrtarget/avrdude/Fuses/FileName= 15 | avrtarget/avrdude/Fuses/MCUid=atmega644 16 | avrtarget/avrdude/Fuses/UseFile=false 17 | avrtarget/avrdude/Fuses/Write=true 18 | avrtarget/avrdude/NoChipErase=false 19 | avrtarget/avrdude/NoSigCheck=false 20 | avrtarget/avrdude/NoVerify=false 21 | avrtarget/avrdude/NoWrite=false 22 | avrtarget/avrdude/OtherOptions= 23 | avrtarget/avrdude/ProgrammerID=programmerconfig.1 24 | avrtarget/avrdude/UseCounter=false 25 | avrtarget/avrdude/WriteEEPROM=false 26 | avrtarget/avrdude/WriteFlash=true 27 | avrtarget/de.innot.avreclipse.configuration.app.release.789230477.1525111634.709383679/ClockFrequency=8000000 28 | avrtarget/de.innot.avreclipse.configuration.app.release.789230477.1525111634.709383679/ExtRAMSize=0 29 | avrtarget/de.innot.avreclipse.configuration.app.release.789230477.1525111634.709383679/ExtendedRAM=false 30 | avrtarget/de.innot.avreclipse.configuration.app.release.789230477.1525111634.709383679/MCUType=atmega1284p 31 | avrtarget/de.innot.avreclipse.configuration.app.release.789230477.1525111634.709383679/UseEEPROM=false 32 | avrtarget/de.innot.avreclipse.configuration.app.release.789230477.1525111634.709383679/UseExtendedRAMforHeap=true 33 | avrtarget/de.innot.avreclipse.configuration.app.release.789230477.1525111634.709383679/avrdude/BitBangDelay= 34 | avrtarget/de.innot.avreclipse.configuration.app.release.789230477.1525111634.709383679/avrdude/Bitclock= 35 | avrtarget/de.innot.avreclipse.configuration.app.release.789230477.1525111634.709383679/avrdude/EEPROMFile= 36 | avrtarget/de.innot.avreclipse.configuration.app.release.789230477.1525111634.709383679/avrdude/EEPROMFromConfig=true 37 | avrtarget/de.innot.avreclipse.configuration.app.release.789230477.1525111634.709383679/avrdude/FlashFile= 38 | avrtarget/de.innot.avreclipse.configuration.app.release.789230477.1525111634.709383679/avrdude/FlashFromConfig=true 39 | avrtarget/de.innot.avreclipse.configuration.app.release.789230477.1525111634.709383679/avrdude/Fuses/ByteValues=194\:209\:252 40 | avrtarget/de.innot.avreclipse.configuration.app.release.789230477.1525111634.709383679/avrdude/Fuses/FileName= 41 | avrtarget/de.innot.avreclipse.configuration.app.release.789230477.1525111634.709383679/avrdude/Fuses/MCUid=atmega1284p 42 | avrtarget/de.innot.avreclipse.configuration.app.release.789230477.1525111634.709383679/avrdude/Fuses/UseFile=false 43 | avrtarget/de.innot.avreclipse.configuration.app.release.789230477.1525111634.709383679/avrdude/Fuses/Write=true 44 | avrtarget/de.innot.avreclipse.configuration.app.release.789230477.1525111634.709383679/avrdude/NoChipErase=false 45 | avrtarget/de.innot.avreclipse.configuration.app.release.789230477.1525111634.709383679/avrdude/NoSigCheck=false 46 | avrtarget/de.innot.avreclipse.configuration.app.release.789230477.1525111634.709383679/avrdude/NoVerify=false 47 | avrtarget/de.innot.avreclipse.configuration.app.release.789230477.1525111634.709383679/avrdude/NoWrite=false 48 | avrtarget/de.innot.avreclipse.configuration.app.release.789230477.1525111634.709383679/avrdude/OtherOptions= 49 | avrtarget/de.innot.avreclipse.configuration.app.release.789230477.1525111634.709383679/avrdude/ProgrammerID=programmerconfig.1 50 | avrtarget/de.innot.avreclipse.configuration.app.release.789230477.1525111634.709383679/avrdude/UseCounter=false 51 | avrtarget/de.innot.avreclipse.configuration.app.release.789230477.1525111634.709383679/avrdude/WriteEEPROM=false 52 | avrtarget/de.innot.avreclipse.configuration.app.release.789230477.1525111634.709383679/avrdude/WriteFlash=true 53 | avrtarget/de.innot.avreclipse.configuration.app.release.789230477.1525111634/ClockFrequency=8000000 54 | avrtarget/de.innot.avreclipse.configuration.app.release.789230477.1525111634/ExtRAMSize=0 55 | avrtarget/de.innot.avreclipse.configuration.app.release.789230477.1525111634/ExtendedRAM=false 56 | avrtarget/de.innot.avreclipse.configuration.app.release.789230477.1525111634/MCUType=atmega644 57 | avrtarget/de.innot.avreclipse.configuration.app.release.789230477.1525111634/UseEEPROM=false 58 | avrtarget/de.innot.avreclipse.configuration.app.release.789230477.1525111634/UseExtendedRAMforHeap=true 59 | avrtarget/de.innot.avreclipse.configuration.app.release.789230477.1525111634/avrdude/BitBangDelay= 60 | avrtarget/de.innot.avreclipse.configuration.app.release.789230477.1525111634/avrdude/Bitclock= 61 | avrtarget/de.innot.avreclipse.configuration.app.release.789230477.1525111634/avrdude/EEPROMFile= 62 | avrtarget/de.innot.avreclipse.configuration.app.release.789230477.1525111634/avrdude/EEPROMFromConfig=true 63 | avrtarget/de.innot.avreclipse.configuration.app.release.789230477.1525111634/avrdude/FlashFile= 64 | avrtarget/de.innot.avreclipse.configuration.app.release.789230477.1525111634/avrdude/FlashFromConfig=true 65 | avrtarget/de.innot.avreclipse.configuration.app.release.789230477.1525111634/avrdude/Fuses/ByteValues=194\:209\:252 66 | avrtarget/de.innot.avreclipse.configuration.app.release.789230477.1525111634/avrdude/Fuses/FileName= 67 | avrtarget/de.innot.avreclipse.configuration.app.release.789230477.1525111634/avrdude/Fuses/MCUid=atmega644 68 | avrtarget/de.innot.avreclipse.configuration.app.release.789230477.1525111634/avrdude/Fuses/UseFile=false 69 | avrtarget/de.innot.avreclipse.configuration.app.release.789230477.1525111634/avrdude/Fuses/Write=true 70 | avrtarget/de.innot.avreclipse.configuration.app.release.789230477.1525111634/avrdude/NoChipErase=false 71 | avrtarget/de.innot.avreclipse.configuration.app.release.789230477.1525111634/avrdude/NoSigCheck=false 72 | avrtarget/de.innot.avreclipse.configuration.app.release.789230477.1525111634/avrdude/NoVerify=false 73 | avrtarget/de.innot.avreclipse.configuration.app.release.789230477.1525111634/avrdude/NoWrite=false 74 | avrtarget/de.innot.avreclipse.configuration.app.release.789230477.1525111634/avrdude/OtherOptions= 75 | avrtarget/de.innot.avreclipse.configuration.app.release.789230477.1525111634/avrdude/ProgrammerID=programmerconfig.1 76 | avrtarget/de.innot.avreclipse.configuration.app.release.789230477.1525111634/avrdude/UseCounter=false 77 | avrtarget/de.innot.avreclipse.configuration.app.release.789230477.1525111634/avrdude/WriteEEPROM=false 78 | avrtarget/de.innot.avreclipse.configuration.app.release.789230477.1525111634/avrdude/WriteFlash=true 79 | avrtarget/perConfig=true 80 | eclipse.preferences.version=1 81 | -------------------------------------------------------------------------------- /lcd_i2c_digital_clock/lcd_i2c_digital_clock.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Jeremy Cole 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program 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. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | */ 19 | 20 | /* 21 | 22 | LCD I2C Digital Clock 23 | ===================== 24 | 25 | An LCD digital clock controlled by I2C, using LCD Backpack, initially 26 | designed to be connected to LED Analog Clock. This code expects an 27 | rtc_datetime_24h_t to be transmitted after an I2C START. For example, 28 | from the I2C master-side, the following code will pass a (locally 29 | created) rtc_datetime_24h_t structure to the LCD I2C Digital Clock for 30 | display: 31 | 32 | void write_remote_lcd(rtc_datetime_24h_t *dt) 33 | { 34 | if(0 == i2c_start(0x70, I2C_WRITE)) 35 | { 36 | i2c_write_array((uint8_t *)dt, 8); 37 | } 38 | i2c_stop(); 39 | } 40 | 41 | In the future, a more robust protocol supporting many more features could 42 | be implemented by collecting a byte "register" before accepting more data. 43 | 44 | */ 45 | 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include 54 | 55 | #define I2C_SCL_CLOCK 400000L 56 | #include 57 | #include 58 | #include 59 | #include 60 | 61 | #define LCD_CON_OCR OCR0A 62 | #define LCD_BKL_OCR OCR0B 63 | 64 | lcd_t lcd = { 65 | .interface = LCD_INTERFACE_8BIT, 66 | .data = {&PINA, &PORTA, &DDRA, PA0}, 67 | .rs = {&PINB, &PORTB, &DDRB, PB1}, 68 | .rw = {&PINB, &PORTB, &DDRB, PB2}, 69 | .e = {&PINB, &PORTB, &DDRB, PB0} 70 | }; 71 | 72 | #define MAX_DATA_AGE_CS 150 73 | 74 | struct { 75 | rtc_datetime_24h_t current_dt; 76 | uint8_t gps_signal_strength; 77 | } data; 78 | uint8_t *data_p; 79 | uint8_t data_age = MAX_DATA_AGE_CS; 80 | 81 | #define CG_GPS_ICON 0 82 | lcd_cg_t cg_gps_icon = { 83 | 0b00000000, 84 | 0b00000000, 85 | 0b00000000, 86 | 0b00000110, 87 | 0b00001000, 88 | 0b00001011, 89 | 0b00001001, 90 | 0b00000110, 91 | }; 92 | 93 | #define CG_GPS_SIGNAL 1 94 | #define CG_GPS_SIGNAL_SIZE 9 95 | lcd_cg_t cg_gps_signal[9] = { 96 | { // 0, "X" drawing 97 | 0b00000000, 98 | 0b00000000, 99 | 0b00000000, 100 | 0b00010001, 101 | 0b00001010, 102 | 0b00000100, 103 | 0b00001010, 104 | 0b00010001, 105 | }, 106 | { // 1 107 | 0b00000000, 108 | 0b00000000, 109 | 0b00000000, 110 | 0b00000000, 111 | 0b00000000, 112 | 0b00000000, 113 | 0b00000000, 114 | 0b00000001, 115 | }, 116 | { // 2 117 | 0b00000000, 118 | 0b00000000, 119 | 0b00000000, 120 | 0b00000000, 121 | 0b00000000, 122 | 0b00000000, 123 | 0b00000001, 124 | 0b00000011, 125 | }, 126 | { // 3 127 | 0b00000000, 128 | 0b00000000, 129 | 0b00000000, 130 | 0b00000000, 131 | 0b00000000, 132 | 0b00000001, 133 | 0b00000011, 134 | 0b00000111, 135 | }, 136 | { // 4 137 | 0b00000000, 138 | 0b00000000, 139 | 0b00000000, 140 | 0b00000000, 141 | 0b00000001, 142 | 0b00000011, 143 | 0b00000111, 144 | 0b00001111, 145 | }, 146 | { // 5 147 | 0b00000000, 148 | 0b00000000, 149 | 0b00000000, 150 | 0b00000001, 151 | 0b00000011, 152 | 0b00000111, 153 | 0b00001111, 154 | 0b00011111, 155 | }, 156 | { // 6 157 | 0b00000000, 158 | 0b00000000, 159 | 0b00000001, 160 | 0b00000011, 161 | 0b00000111, 162 | 0b00001111, 163 | 0b00011111, 164 | 0b00011111, 165 | }, 166 | { // 7 167 | 0b00000000, 168 | 0b00000001, 169 | 0b00000011, 170 | 0b00000111, 171 | 0b00001111, 172 | 0b00011111, 173 | 0b00011111, 174 | 0b00011111, 175 | }, 176 | { // 8 177 | 0b00000001, 178 | 0b00000011, 179 | 0b00000111, 180 | 0b00001111, 181 | 0b00011111, 182 | 0b00011111, 183 | 0b00011111, 184 | 0b00011111, 185 | }, 186 | }; 187 | 188 | uint8_t handle_i2c_slave_rx(uint8_t status, i2c_mode_t last_mode, i2c_mode_t current_mode) 189 | { 190 | if(last_mode != current_mode) 191 | { 192 | data_p = (uint8_t *)&data; 193 | } 194 | 195 | if(status == TW_SR_DATA_ACK || status == TW_SR_DATA_NACK) 196 | *data_p++ = TWDR; 197 | 198 | data_age = 0; 199 | 200 | return 0; 201 | } 202 | 203 | int main(void) 204 | { 205 | uart_t *u0; 206 | char s[32]; 207 | 208 | _delay_ms(1000); 209 | 210 | u0 = uart_init("0", UART_BAUD_SELECT(38400, F_CPU)); 211 | uart_init_stdout(u0); 212 | 213 | i2c_init(); 214 | i2c_slave_init(0x70, I2C_ADDRESS_MASK_SINGLE, I2C_GCALL_DISABLED); 215 | i2c_global.sr_callback = handle_i2c_slave_rx; 216 | 217 | DDRB |= _BV(PB3) | _BV(PB4); 218 | 219 | /* 220 | COM0A1 = Clear OC0A on compare match 221 | COM0B1 = Clear OC0B on compare match 222 | WGM01|WGM00 = Fast PWM 223 | */ 224 | TCCR0A = _BV(COM0A1) | _BV(COM0B1) | _BV(WGM01) | _BV(WGM00); 225 | /* CS01 = Prescale by /8 */ 226 | TCCR0B = _BV(CS01); 227 | 228 | LCD_CON_OCR = 90; 229 | LCD_BKL_OCR = 255; 230 | 231 | sei(); 232 | 233 | printf("\n\nBooted up!\n"); 234 | 235 | lcd_init(&lcd); 236 | 237 | lcd_cg_define(&lcd, CG_GPS_ICON, cg_gps_icon); 238 | lcd_cg_define(&lcd, CG_GPS_SIGNAL, cg_gps_signal[0]); 239 | 240 | while(1) 241 | { 242 | if(data_age == 0) 243 | { 244 | // Re-define the CG_GPS_SIGNAL character to a depiction of the current 245 | // signal strength (an "X" for no signal, or a number of bars). 246 | lcd_cg_define(&lcd, CG_GPS_SIGNAL, 247 | cg_gps_signal[data.gps_signal_strength]); 248 | 249 | sprintf(s, "%-10s%-4s%2i", 250 | rtc_dow_names[data.current_dt.day_of_week], 251 | rtc_month_abbreviations[data.current_dt.month], 252 | data.current_dt.date); 253 | lcd_move_cursor(&lcd, 0, 0); 254 | lcd_write_string(&lcd, s, strlen(s)); 255 | 256 | sprintf(s, " %02i:%02i:%02i ", 257 | data.current_dt.hour, 258 | data.current_dt.minute, 259 | data.current_dt.second); 260 | lcd_move_cursor(&lcd, 1, 0); 261 | lcd_write_string(&lcd, s, strlen(s)); 262 | 263 | // Draw the "G" icon. 264 | lcd_move_cursor(&lcd, 1, 14); 265 | lcd_write_char(&lcd, CG_GPS_ICON); 266 | 267 | // Draw the previously defined signal strength icon. 268 | lcd_move_cursor(&lcd, 1, 15); 269 | lcd_write_char(&lcd, CG_GPS_SIGNAL); 270 | 271 | // Between 9pm and 6am, dim the display, otherwise maximum brightness. 272 | if(data.current_dt.hour >= 6 && data.current_dt.hour < 21) 273 | LCD_BKL_OCR = 255; 274 | else 275 | LCD_BKL_OCR = 64; 276 | 277 | } else if(data_age == MAX_DATA_AGE_CS) { 278 | // The last data we've received is too old to display. It's better to 279 | // display an error than an incorrect time. 280 | LCD_BKL_OCR = 255; 281 | lcd_clear(&lcd); 282 | lcd_move_cursor(&lcd, 0, 0); 283 | lcd_write_string(&lcd, "Waiting for", 11); 284 | lcd_move_cursor(&lcd, 1, 5); 285 | lcd_write_string(&lcd, "valid data!", 11); 286 | } 287 | 288 | if(data_age <= MAX_DATA_AGE_CS) { 289 | data_age++; 290 | } 291 | 292 | _delay_ms(10); 293 | } 294 | 295 | return(0); 296 | } 297 | -------------------------------------------------------------------------------- /lcd_test/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | lcd_test 4 | 5 | 6 | lcd 7 | uart 8 | 9 | 10 | 11 | org.eclipse.cdt.managedbuilder.core.genmakebuilder 12 | clean,full,incremental, 13 | 14 | 15 | ?name? 16 | 17 | 18 | 19 | org.eclipse.cdt.make.core.append_environment 20 | true 21 | 22 | 23 | org.eclipse.cdt.make.core.autoBuildTarget 24 | all 25 | 26 | 27 | org.eclipse.cdt.make.core.buildArguments 28 | 29 | 30 | 31 | org.eclipse.cdt.make.core.buildCommand 32 | make 33 | 34 | 35 | org.eclipse.cdt.make.core.buildLocation 36 | ${workspace_loc:/lcd_test/Release} 37 | 38 | 39 | org.eclipse.cdt.make.core.cleanBuildTarget 40 | clean 41 | 42 | 43 | org.eclipse.cdt.make.core.contents 44 | org.eclipse.cdt.make.core.activeConfigSettings 45 | 46 | 47 | org.eclipse.cdt.make.core.enableAutoBuild 48 | false 49 | 50 | 51 | org.eclipse.cdt.make.core.enableCleanBuild 52 | true 53 | 54 | 55 | org.eclipse.cdt.make.core.enableFullBuild 56 | true 57 | 58 | 59 | org.eclipse.cdt.make.core.fullBuildTarget 60 | all 61 | 62 | 63 | org.eclipse.cdt.make.core.stopOnError 64 | true 65 | 66 | 67 | org.eclipse.cdt.make.core.useDefaultBuildCmd 68 | true 69 | 70 | 71 | 72 | 73 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder 74 | 75 | 76 | 77 | 78 | 79 | org.eclipse.cdt.core.cnature 80 | org.eclipse.cdt.managedbuilder.core.managedBuildNature 81 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature 82 | de.innot.avreclipse.core.avrnature 83 | 84 | 85 | -------------------------------------------------------------------------------- /lcd_test/.settings/de.innot.avreclipse.core.prefs: -------------------------------------------------------------------------------- 1 | #Sun Oct 24 16:34:58 PDT 2010 2 | avrtarget/ClockFrequency=8000000 3 | avrtarget/ExtRAMSize=0 4 | avrtarget/ExtendedRAM=false 5 | avrtarget/MCUType=atmega644 6 | avrtarget/UseEEPROM=false 7 | avrtarget/UseExtendedRAMforHeap=true 8 | avrtarget/avrdude/BitBangDelay= 9 | avrtarget/avrdude/Bitclock=10 10 | avrtarget/avrdude/EEPROMFile= 11 | avrtarget/avrdude/EEPROMFromConfig=true 12 | avrtarget/avrdude/FlashFile= 13 | avrtarget/avrdude/FlashFromConfig=true 14 | avrtarget/avrdude/Fuses/ByteValues=194\:217\:255 15 | avrtarget/avrdude/Fuses/FileName= 16 | avrtarget/avrdude/Fuses/MCUid=atmega644 17 | avrtarget/avrdude/Fuses/UseFile=false 18 | avrtarget/avrdude/Fuses/Write=true 19 | avrtarget/avrdude/NoChipErase=false 20 | avrtarget/avrdude/NoSigCheck=false 21 | avrtarget/avrdude/NoVerify=false 22 | avrtarget/avrdude/NoWrite=false 23 | avrtarget/avrdude/OtherOptions= 24 | avrtarget/avrdude/ProgrammerID=programmerconfig.1 25 | avrtarget/avrdude/UseCounter=false 26 | avrtarget/avrdude/WriteEEPROM=false 27 | avrtarget/avrdude/WriteFlash=true 28 | avrtarget/perConfig=false 29 | eclipse.preferences.version=1 30 | -------------------------------------------------------------------------------- /lcd_test/lcd_test.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Jeremy Cole 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program 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. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include 30 | #include 31 | 32 | #define LCD_CON_OCR OCR0A 33 | #define LCD_BKL_OCR OCR0B 34 | 35 | lcd_t lcd = { 36 | .interface = LCD_INTERFACE_8BIT, 37 | .data = {&PINA, &PORTA, &DDRA, PA0}, 38 | .rs = {&PINB, &PORTB, &DDRB, PB1}, 39 | .rw = {&PINB, &PORTB, &DDRB, PB2}, 40 | .e = {&PINB, &PORTB, &DDRB, PB0} 41 | }; 42 | 43 | int main(void) 44 | { 45 | uart_t *u0; 46 | char s[32]; 47 | uint16_t x = 0; 48 | 49 | _delay_ms(1000); 50 | 51 | u0 = uart_init("0", UART_BAUD_SELECT(38400, F_CPU)); 52 | uart_init_stdout(u0); 53 | 54 | DDRB |= _BV(PB3) | _BV(PB4); 55 | 56 | /* 57 | COM0A1 = Clear OC0A on compare match 58 | COM0B1 = Clear OC0B on compare match 59 | WGM01|WGM00 = Fast PWM 60 | */ 61 | TCCR0A = _BV(COM0A1) | _BV(COM0B1) | _BV(WGM01) | _BV(WGM00); 62 | /* CS01 = Prescale by /8 */ 63 | TCCR0B = _BV(CS01); 64 | 65 | LCD_CON_OCR = 90; 66 | LCD_BKL_OCR = 255; 67 | 68 | sei(); 69 | 70 | printf("\n\nBooted up!\n"); 71 | 72 | lcd_init(&lcd); 73 | 74 | while(1) 75 | { 76 | if(0 == (x%26)) 77 | lcd_clear(&lcd); 78 | 79 | sprintf(s, "%-11s%5i", "Test String", x); 80 | lcd_move_cursor(&lcd, 0, 0); 81 | lcd_write_string(&lcd, s, strlen(s)); 82 | 83 | lcd_move_cursor(&lcd, 1, x%16); 84 | lcd_write_char(&lcd, x%26+'a'); 85 | 86 | _delay_ms(200); 87 | x++; 88 | } 89 | 90 | return(0); 91 | } 92 | -------------------------------------------------------------------------------- /led_analog_clock/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | led_analog_clock 4 | 5 | 6 | i2c 7 | led_charlieplex 8 | led_sequencer 9 | rtc 10 | uart 11 | 12 | 13 | 14 | org.eclipse.cdt.managedbuilder.core.genmakebuilder 15 | clean,full,incremental, 16 | 17 | 18 | ?name? 19 | 20 | 21 | 22 | org.eclipse.cdt.make.core.append_environment 23 | true 24 | 25 | 26 | org.eclipse.cdt.make.core.autoBuildTarget 27 | all 28 | 29 | 30 | org.eclipse.cdt.make.core.buildArguments 31 | 32 | 33 | 34 | org.eclipse.cdt.make.core.buildCommand 35 | make 36 | 37 | 38 | org.eclipse.cdt.make.core.buildLocation 39 | ${workspace_loc:/led_analog_clock_v1/Release} 40 | 41 | 42 | org.eclipse.cdt.make.core.cleanBuildTarget 43 | clean 44 | 45 | 46 | org.eclipse.cdt.make.core.contents 47 | org.eclipse.cdt.make.core.activeConfigSettings 48 | 49 | 50 | org.eclipse.cdt.make.core.enableAutoBuild 51 | false 52 | 53 | 54 | org.eclipse.cdt.make.core.enableCleanBuild 55 | true 56 | 57 | 58 | org.eclipse.cdt.make.core.enableFullBuild 59 | true 60 | 61 | 62 | org.eclipse.cdt.make.core.fullBuildTarget 63 | all 64 | 65 | 66 | org.eclipse.cdt.make.core.stopOnError 67 | true 68 | 69 | 70 | org.eclipse.cdt.make.core.useDefaultBuildCmd 71 | true 72 | 73 | 74 | 75 | 76 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder 77 | 78 | 79 | 80 | 81 | 82 | org.eclipse.cdt.core.cnature 83 | org.eclipse.cdt.managedbuilder.core.managedBuildNature 84 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature 85 | de.innot.avreclipse.core.avrnature 86 | 87 | 88 | -------------------------------------------------------------------------------- /led_analog_clock/.settings/de.innot.avreclipse.core.prefs: -------------------------------------------------------------------------------- 1 | avrtarget/ClockFrequency=8000000 2 | avrtarget/ExtRAMSize=0 3 | avrtarget/ExtendedRAM=false 4 | avrtarget/MCUType=atmega644 5 | avrtarget/UseEEPROM=false 6 | avrtarget/UseExtendedRAMforHeap=true 7 | avrtarget/avrdude/BitBangDelay= 8 | avrtarget/avrdude/Bitclock= 9 | avrtarget/avrdude/EEPROMFile= 10 | avrtarget/avrdude/EEPROMFromConfig=true 11 | avrtarget/avrdude/FlashFile= 12 | avrtarget/avrdude/FlashFromConfig=true 13 | avrtarget/avrdude/Fuses/ByteValues=194\:209\:252 14 | avrtarget/avrdude/Fuses/FileName= 15 | avrtarget/avrdude/Fuses/MCUid=atmega644 16 | avrtarget/avrdude/Fuses/UseFile=false 17 | avrtarget/avrdude/Fuses/Write=true 18 | avrtarget/avrdude/NoChipErase=false 19 | avrtarget/avrdude/NoSigCheck=false 20 | avrtarget/avrdude/NoVerify=false 21 | avrtarget/avrdude/NoWrite=false 22 | avrtarget/avrdude/OtherOptions= 23 | avrtarget/avrdude/ProgrammerID=programmerconfig.1 24 | avrtarget/avrdude/UseCounter=false 25 | avrtarget/avrdude/WriteEEPROM=false 26 | avrtarget/avrdude/WriteFlash=true 27 | avrtarget/de.innot.avreclipse.configuration.app.release.2119175456.1762794471/ClockFrequency=8000000 28 | avrtarget/de.innot.avreclipse.configuration.app.release.2119175456.1762794471/ExtRAMSize=0 29 | avrtarget/de.innot.avreclipse.configuration.app.release.2119175456.1762794471/ExtendedRAM=false 30 | avrtarget/de.innot.avreclipse.configuration.app.release.2119175456.1762794471/MCUType=atmega644 31 | avrtarget/de.innot.avreclipse.configuration.app.release.2119175456.1762794471/UseEEPROM=false 32 | avrtarget/de.innot.avreclipse.configuration.app.release.2119175456.1762794471/UseExtendedRAMforHeap=true 33 | avrtarget/de.innot.avreclipse.configuration.app.release.2119175456.1762794471/avrdude/BitBangDelay= 34 | avrtarget/de.innot.avreclipse.configuration.app.release.2119175456.1762794471/avrdude/Bitclock= 35 | avrtarget/de.innot.avreclipse.configuration.app.release.2119175456.1762794471/avrdude/EEPROMFile= 36 | avrtarget/de.innot.avreclipse.configuration.app.release.2119175456.1762794471/avrdude/EEPROMFromConfig=true 37 | avrtarget/de.innot.avreclipse.configuration.app.release.2119175456.1762794471/avrdude/FlashFile= 38 | avrtarget/de.innot.avreclipse.configuration.app.release.2119175456.1762794471/avrdude/FlashFromConfig=true 39 | avrtarget/de.innot.avreclipse.configuration.app.release.2119175456.1762794471/avrdude/NoChipErase=false 40 | avrtarget/de.innot.avreclipse.configuration.app.release.2119175456.1762794471/avrdude/NoSigCheck=false 41 | avrtarget/de.innot.avreclipse.configuration.app.release.2119175456.1762794471/avrdude/NoVerify=false 42 | avrtarget/de.innot.avreclipse.configuration.app.release.2119175456.1762794471/avrdude/NoWrite=false 43 | avrtarget/de.innot.avreclipse.configuration.app.release.2119175456.1762794471/avrdude/OtherOptions= 44 | avrtarget/de.innot.avreclipse.configuration.app.release.2119175456.1762794471/avrdude/ProgrammerID=programmerconfig.1 45 | avrtarget/de.innot.avreclipse.configuration.app.release.2119175456.1762794471/avrdude/UseCounter=false 46 | avrtarget/de.innot.avreclipse.configuration.app.release.2119175456.1762794471/avrdude/WriteEEPROM=false 47 | avrtarget/de.innot.avreclipse.configuration.app.release.2119175456.1762794471/avrdude/WriteFlash=true 48 | avrtarget/perConfig=true 49 | eclipse.preferences.version=1 50 | -------------------------------------------------------------------------------- /led_analog_clock/led_analog_clock_v1.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Jeremy Cole 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program 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. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | */ 19 | 20 | #include 21 | #include 22 | 23 | #include 24 | 25 | #include "led_analog_clock_v1.h" 26 | 27 | led_charlieplex_port_t led_analog_clock_v1_ports[] = { 28 | /* 0 */ { &PINA, &DDRA, &PORTA, 0xff }, 29 | /* 1 */ { &PINC, &DDRC, &PORTC, 0xff }, 30 | { NULL, NULL, NULL, 0 }, 31 | }; 32 | 33 | led_charlieplex_led_t led_analog_clock_v1_leds[] = { 34 | { "AA1", 0, 0, 1, 0 }, 35 | { "AB1", 0, 0, 1, 1 }, 36 | { "AC1", 0, 0, 1, 2 }, 37 | { "AD1", 0, 0, 1, 3 }, 38 | { "AE1", 0, 0, 1, 4 }, 39 | { "AF1", 0, 0, 1, 5 }, 40 | { "AG1", 0, 0, 1, 6 }, 41 | { "AH1", 0, 0, 1, 7 }, 42 | 43 | { "AA2", 1, 0, 0, 0 }, 44 | { "AB2", 1, 1, 0, 0 }, 45 | { "AC2", 1, 2, 0, 0 }, 46 | { "AD2", 1, 3, 0, 0 }, 47 | { "AE2", 1, 4, 0, 0 }, 48 | { "AF2", 1, 5, 0, 0 }, 49 | { "AG2", 1, 6, 0, 0 }, 50 | { "AH2", 1, 7, 0, 0 }, 51 | 52 | { "BA1", 0, 1, 1, 0 }, 53 | { "BB1", 0, 1, 1, 1 }, 54 | { "BC1", 0, 1, 1, 2 }, 55 | { "BD1", 0, 1, 1, 3 }, 56 | { "BE1", 0, 1, 1, 4 }, 57 | { "BF1", 0, 1, 1, 5 }, 58 | { "BG1", 0, 1, 1, 6 }, 59 | { "BH1", 0, 1, 1, 7 }, 60 | 61 | { "BA2", 1, 0, 0, 1 }, 62 | { "BB2", 1, 1, 0, 1 }, 63 | { "BC2", 1, 2, 0, 1 }, 64 | { "BD2", 1, 3, 0, 1 }, 65 | { "BE2", 1, 4, 0, 1 }, 66 | { "BF2", 1, 5, 0, 1 }, 67 | { "BG2", 1, 6, 0, 1 }, 68 | { "BH2", 1, 7, 0, 1 }, 69 | 70 | { "CA1", 0, 2, 1, 0 }, 71 | { "CB1", 0, 2, 1, 1 }, 72 | { "CC1", 0, 2, 1, 2 }, 73 | { "CD1", 0, 2, 1, 3 }, 74 | { "CE1", 0, 2, 1, 4 }, 75 | { "CF1", 0, 2, 1, 5 }, 76 | { "CG1", 0, 2, 1, 6 }, 77 | { "CH1", 0, 2, 1, 7 }, 78 | 79 | { "CA2", 1, 0, 0, 2 }, 80 | { "CB2", 1, 1, 0, 2 }, 81 | { "CC2", 1, 2, 0, 2 }, 82 | { "CD2", 1, 3, 0, 2 }, 83 | { "CE2", 1, 4, 0, 2 }, 84 | { "CF2", 1, 5, 0, 2 }, 85 | { "CG2", 1, 6, 0, 2 }, 86 | { "CH2", 1, 7, 0, 2 }, 87 | 88 | { "DA1", 0, 3, 1, 0 }, 89 | { "DB1", 0, 3, 1, 1 }, 90 | { "DC1", 0, 3, 1, 2 }, 91 | { "DD1", 0, 3, 1, 3 }, 92 | { "DE1", 0, 3, 1, 4 }, 93 | { "DF1", 0, 3, 1, 5 }, 94 | { "DG1", 0, 3, 1, 6 }, 95 | { "DH1", 0, 3, 1, 7 }, 96 | 97 | { "DA2", 1, 0, 0, 3 }, 98 | { "DB2", 1, 1, 0, 3 }, 99 | { "DC2", 1, 2, 0, 3 }, 100 | { "DD2", 1, 3, 0, 3 }, 101 | { "DE2", 1, 4, 0, 3 }, 102 | { "DF2", 1, 5, 0, 3 }, 103 | { "DG2", 1, 6, 0, 3 }, 104 | { "DH2", 1, 7, 0, 3 }, 105 | 106 | { "EA1", 0, 4, 1, 0 }, 107 | { "EB1", 0, 4, 1, 1 }, 108 | { "EC1", 0, 4, 1, 2 }, 109 | { "ED1", 0, 4, 1, 3 }, 110 | { "EE1", 0, 4, 1, 4 }, 111 | { "EF1", 0, 4, 1, 5 }, 112 | { "EG1", 0, 4, 1, 6 }, 113 | { "EH1", 0, 4, 1, 7 }, 114 | 115 | { "EA2", 1, 0, 0, 4 }, 116 | { "EB2", 1, 1, 0, 4 }, 117 | { "EC2", 1, 2, 0, 4 }, 118 | { "ED2", 1, 3, 0, 4 }, 119 | { "EE2", 1, 4, 0, 4 }, 120 | { "EF2", 1, 5, 0, 4 }, 121 | { "EG2", 1, 6, 0, 4 }, 122 | { "EH2", 1, 7, 0, 4 }, 123 | 124 | { "FA1", 0, 5, 1, 0 }, 125 | { "FB1", 0, 5, 1, 1 }, 126 | { "FC1", 0, 5, 1, 2 }, 127 | { "FD1", 0, 5, 1, 3 }, 128 | { "FE1", 0, 5, 1, 4 }, 129 | { "FF1", 0, 5, 1, 5 }, 130 | { "FG1", 0, 5, 1, 6 }, 131 | { "FH1", 0, 5, 1, 7 }, 132 | 133 | { "FA2", 1, 0, 0, 5 }, 134 | { "FB2", 1, 1, 0, 5 }, 135 | { "FC2", 1, 2, 0, 5 }, 136 | { "FD2", 1, 3, 0, 5 }, 137 | { "FE2", 1, 4, 0, 5 }, 138 | { "FF2", 1, 5, 0, 5 }, 139 | { "FG2", 1, 6, 0, 5 }, 140 | { "FH2", 1, 7, 0, 5 }, 141 | 142 | { "GA1", 0, 6, 1, 0 }, 143 | { "GB1", 0, 6, 1, 1 }, 144 | { "GC1", 0, 6, 1, 2 }, 145 | { "GD1", 0, 6, 1, 3 }, 146 | { "GE1", 0, 6, 1, 4 }, 147 | { "GF1", 0, 6, 1, 5 }, 148 | { "GG1", 0, 6, 1, 6 }, 149 | { "GH1", 0, 6, 1, 7 }, 150 | 151 | { "GA2", 1, 0, 0, 6 }, 152 | { "GB2", 1, 1, 0, 6 }, 153 | { "GC2", 1, 2, 0, 6 }, 154 | { "GD2", 1, 3, 0, 6 }, 155 | { "GE2", 1, 4, 0, 6 }, 156 | { "GF2", 1, 5, 0, 6 }, 157 | { "GG2", 1, 6, 0, 6 }, 158 | { "GH2", 1, 7, 0, 6 }, 159 | 160 | { "HA1", 0, 7, 1, 0 }, 161 | { "HB1", 0, 7, 1, 1 }, 162 | { "HC1", 0, 7, 1, 2 }, 163 | { "HD1", 0, 7, 1, 3 }, 164 | { "HE1", 0, 7, 1, 4 }, 165 | { "HF1", 0, 7, 1, 5 }, 166 | { "HG1", 0, 7, 1, 6 }, 167 | { "HH1", 0, 7, 1, 7 }, 168 | 169 | { "HA2", 1, 0, 0, 7 }, 170 | { "HB2", 1, 1, 0, 7 }, 171 | { "HC2", 1, 2, 0, 7 }, 172 | { "HD2", 1, 3, 0, 7 }, 173 | { "HE2", 1, 4, 0, 7 }, 174 | { "HF2", 1, 5, 0, 7 }, 175 | { "HG2", 1, 6, 0, 7 }, 176 | { "HH2", 1, 7, 0, 7 }, 177 | 178 | { NULL, 0, 0, 0, 0 } 179 | }; 180 | 181 | led_charlieplex_t led_analog_clock_v1 = { 182 | 0, 183 | led_analog_clock_v1_ports, 184 | led_analog_clock_v1_leds 185 | }; 186 | 187 | -------------------------------------------------------------------------------- /led_analog_clock/led_analog_clock_v1.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Jeremy Cole 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program 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. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | */ 19 | 20 | #ifndef LED_ANALOG_CLOCK_V1_H 21 | #define LED_ANALOG_CLOCK_V1_H 22 | 23 | #include 24 | 25 | led_charlieplex_t led_analog_clock_v1; 26 | 27 | #endif /* LED_ANALOG_CLOCK_V1_H */ 28 | -------------------------------------------------------------------------------- /led_analog_clock/led_analog_clock_v2.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Jeremy Cole 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program 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. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | */ 19 | 20 | #include 21 | #include 22 | 23 | #include 24 | 25 | #include "led_analog_clock_v2.h" 26 | 27 | led_charlieplex_port_t led_analog_clock_v2_ports[] = { 28 | /* 0 */ { &PINA, &DDRA, &PORTA, 0xff }, 29 | /* 1 */ { &PINB, &DDRB, &PORTB, (_BV(PB0) | _BV(PB1) | _BV(PB2) | _BV(PB3)) }, 30 | /* 2 */ { &PIND, &DDRD, &PORTD, (_BV(PD4) | _BV(PD5) | _BV(PD6) | _BV(PD7)) }, 31 | { NULL, NULL, NULL, 0 }, 32 | }; 33 | 34 | led_charlieplex_led_t led_analog_clock_v2_leds[] = { 35 | { "AA1", 0, 0, 2, 4 }, 36 | { "AB1", 0, 0, 2, 5 }, 37 | { "AC1", 0, 0, 2, 6 }, 38 | { "AD1", 0, 0, 2, 7 }, 39 | { "AE1", 0, 0, 1, 0 }, 40 | { "AF1", 0, 0, 1, 1 }, 41 | { "AG1", 0, 0, 1, 2 }, 42 | { "AH1", 0, 0, 1, 3 }, 43 | 44 | { "AA2", 2, 4, 0, 0 }, 45 | { "AB2", 2, 5, 0, 0 }, 46 | { "AC2", 2, 6, 0, 0 }, 47 | { "AD2", 2, 7, 0, 0 }, 48 | { "AE2", 1, 0, 0, 0 }, 49 | { "AF2", 1, 1, 0, 0 }, 50 | { "AG2", 1, 2, 0, 0 }, 51 | { "AH2", 1, 3, 0, 0 }, 52 | 53 | { "BA1", 0, 1, 2, 4 }, 54 | { "BB1", 0, 1, 2, 5 }, 55 | { "BC1", 0, 1, 2, 6 }, 56 | { "BD1", 0, 1, 2, 7 }, 57 | { "BE1", 0, 1, 1, 0 }, 58 | { "BF1", 0, 1, 1, 1 }, 59 | { "BG1", 0, 1, 1, 2 }, 60 | { "BH1", 0, 1, 1, 3 }, 61 | 62 | { "BA2", 2, 4, 0, 1 }, 63 | { "BB2", 2, 5, 0, 1 }, 64 | { "BC2", 2, 6, 0, 1 }, 65 | { "BD2", 2, 7, 0, 1 }, 66 | { "BE2", 1, 0, 0, 1 }, 67 | { "BF2", 1, 1, 0, 1 }, 68 | { "BG2", 1, 2, 0, 1 }, 69 | { "BH2", 1, 3, 0, 1 }, 70 | 71 | { "CA1", 0, 2, 2, 4 }, 72 | { "CB1", 0, 2, 2, 5 }, 73 | { "CC1", 0, 2, 2, 6 }, 74 | { "CD1", 0, 2, 2, 7 }, 75 | { "CE1", 0, 2, 1, 0 }, 76 | { "CF1", 0, 2, 1, 1 }, 77 | { "CG1", 0, 2, 1, 2 }, 78 | { "CH1", 0, 2, 1, 3 }, 79 | 80 | { "CA2", 2, 4, 0, 2 }, 81 | { "CB2", 2, 5, 0, 2 }, 82 | { "CC2", 2, 6, 0, 2 }, 83 | { "CD2", 2, 7, 0, 2 }, 84 | { "CE2", 1, 0, 0, 2 }, 85 | { "CF2", 1, 1, 0, 2 }, 86 | { "CG2", 1, 2, 0, 2 }, 87 | { "CH2", 1, 3, 0, 2 }, 88 | 89 | { "DA1", 0, 3, 2, 4 }, 90 | { "DB1", 0, 3, 2, 5 }, 91 | { "DC1", 0, 3, 2, 6 }, 92 | { "DD1", 0, 3, 2, 7 }, 93 | { "DE1", 0, 3, 1, 0 }, 94 | { "DF1", 0, 3, 1, 1 }, 95 | { "DG1", 0, 3, 1, 2 }, 96 | { "DH1", 0, 3, 1, 3 }, 97 | 98 | { "DA2", 2, 4, 0, 3 }, 99 | { "DB2", 2, 5, 0, 3 }, 100 | { "DC2", 2, 6, 0, 3 }, 101 | { "DD2", 2, 7, 0, 3 }, 102 | { "DE2", 1, 0, 0, 3 }, 103 | { "DF2", 1, 1, 0, 3 }, 104 | { "DG2", 1, 2, 0, 3 }, 105 | { "DH2", 1, 3, 0, 3 }, 106 | 107 | { "EA1", 0, 4, 2, 4 }, 108 | { "EB1", 0, 4, 2, 5 }, 109 | { "EC1", 0, 4, 2, 6 }, 110 | { "ED1", 0, 4, 2, 7 }, 111 | { "EE1", 0, 4, 1, 0 }, 112 | { "EF1", 0, 4, 1, 1 }, 113 | { "EG1", 0, 4, 1, 2 }, 114 | { "EH1", 0, 4, 1, 3 }, 115 | 116 | { "EA2", 2, 4, 0, 4 }, 117 | { "EB2", 2, 5, 0, 4 }, 118 | { "EC2", 2, 6, 0, 4 }, 119 | { "ED2", 2, 7, 0, 4 }, 120 | { "EE2", 1, 0, 0, 4 }, 121 | { "EF2", 1, 1, 0, 4 }, 122 | { "EG2", 1, 2, 0, 4 }, 123 | { "EH2", 1, 3, 0, 4 }, 124 | 125 | { "FA1", 0, 5, 2, 4 }, 126 | { "FB1", 0, 5, 2, 5 }, 127 | { "FC1", 0, 5, 2, 6 }, 128 | { "FD1", 0, 5, 2, 7 }, 129 | { "FE1", 0, 5, 1, 0 }, 130 | { "FF1", 0, 5, 1, 1 }, 131 | { "FG1", 0, 5, 1, 2 }, 132 | { "FH1", 0, 5, 1, 3 }, 133 | 134 | { "FA2", 2, 4, 0, 5 }, 135 | { "FB2", 2, 5, 0, 5 }, 136 | { "FC2", 2, 6, 0, 5 }, 137 | { "FD2", 2, 7, 0, 5 }, 138 | { "FE2", 1, 0, 0, 5 }, 139 | { "FF2", 1, 1, 0, 5 }, 140 | { "FG2", 1, 2, 0, 5 }, 141 | { "FH2", 1, 3, 0, 5 }, 142 | 143 | { "GA1", 0, 6, 2, 4 }, 144 | { "GB1", 0, 6, 2, 5 }, 145 | { "GC1", 0, 6, 2, 6 }, 146 | { "GD1", 0, 6, 2, 7 }, 147 | { "GE1", 0, 6, 1, 0 }, 148 | { "GF1", 0, 6, 1, 1 }, 149 | { "GG1", 0, 6, 1, 2 }, 150 | { "GH1", 0, 6, 1, 3 }, 151 | 152 | { "GA2", 2, 4, 0, 6 }, 153 | { "GB2", 2, 5, 0, 6 }, 154 | { "GC2", 2, 6, 0, 6 }, 155 | { "GD2", 2, 7, 0, 6 }, 156 | { "GE2", 1, 0, 0, 6 }, 157 | { "GF2", 1, 1, 0, 6 }, 158 | { "GG2", 1, 2, 0, 6 }, 159 | { "GH2", 1, 3, 0, 6 }, 160 | 161 | { "HA1", 0, 7, 2, 4 }, 162 | { "HB1", 0, 7, 2, 5 }, 163 | { "HC1", 0, 7, 2, 6 }, 164 | { "HD1", 0, 7, 2, 7 }, 165 | { "HE1", 0, 7, 1, 0 }, 166 | { "HF1", 0, 7, 1, 1 }, 167 | { "HG1", 0, 7, 1, 2 }, 168 | { "HH1", 0, 7, 1, 3 }, 169 | 170 | { "HA2", 2, 4, 0, 7 }, 171 | { "HB2", 2, 5, 0, 7 }, 172 | { "HC2", 2, 6, 0, 7 }, 173 | { "HD2", 2, 7, 0, 7 }, 174 | { "HE2", 1, 0, 0, 7 }, 175 | { "HF2", 1, 1, 0, 7 }, 176 | { "HG2", 1, 2, 0, 7 }, 177 | { "HH2", 1, 3, 0, 7 }, 178 | 179 | { NULL, 0, 0, 0, 0 } 180 | }; 181 | 182 | led_charlieplex_t led_analog_clock_v2 = { 183 | 0, 184 | led_analog_clock_v2_ports, 185 | led_analog_clock_v2_leds 186 | }; 187 | 188 | -------------------------------------------------------------------------------- /led_analog_clock/led_analog_clock_v2.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Jeremy Cole 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program 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. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | */ 19 | 20 | #ifndef LED_ANALOG_CLOCK_V2_H 21 | #define LED_ANALOG_CLOCK_V2_H 22 | 23 | #include 24 | 25 | led_charlieplex_t led_analog_clock_v2; 26 | 27 | #endif /* LED_ANALOG_CLOCK_V2_H */ 28 | -------------------------------------------------------------------------------- /led_analog_clock/led_analog_watch_v1.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Jeremy Cole 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program 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. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | */ 19 | 20 | #include 21 | #include 22 | 23 | #include 24 | 25 | #include "led_analog_watch_v1.h" 26 | 27 | led_charlieplex_port_t led_analog_watch_v1_ports[] = { 28 | /* 0 */ { &PINA, &DDRA, &PORTA, 0xff }, 29 | /* 1 */ { &PINB, &DDRB, &PORTB, (_BV(PB0) | _BV(PB1) | _BV(PB2) | _BV(PB3)) }, 30 | /* 2 */ { &PIND, &DDRD, &PORTD, (_BV(PD4) | _BV(PD5) | _BV(PD6) | _BV(PD7)) }, 31 | { NULL, NULL, NULL, 0 }, 32 | }; 33 | 34 | led_charlieplex_led_t led_analog_watch_v1_leds[] = { 35 | { "AA1", 0, 0, 2, 4 }, 36 | { "AB1", 0, 0, 2, 5 }, 37 | { "AC1", 0, 0, 2, 6 }, 38 | { "AD1", 0, 0, 2, 7 }, 39 | { "AE1", 0, 0, 1, 0 }, 40 | { "AF1", 0, 0, 1, 1 }, 41 | { "AG1", 0, 0, 1, 2 }, 42 | { "AH1", 0, 0, 1, 3 }, 43 | 44 | { "AA2", 2, 4, 0, 0 }, 45 | { "AB2", 2, 5, 0, 0 }, 46 | { "AC2", 2, 6, 0, 0 }, 47 | { "AD2", 2, 7, 0, 0 }, 48 | { "AE2", 1, 0, 0, 0 }, 49 | { "AF2", 1, 1, 0, 0 }, 50 | { "AG2", 1, 2, 0, 0 }, 51 | { "AH2", 1, 3, 0, 0 }, 52 | 53 | { "BA1", 0, 1, 2, 4 }, 54 | { "BB1", 0, 1, 2, 5 }, 55 | { "BC1", 0, 1, 2, 6 }, 56 | { "BD1", 0, 1, 2, 7 }, 57 | { "BE1", 0, 1, 1, 0 }, 58 | { "BF1", 0, 1, 1, 1 }, 59 | { "BG1", 0, 1, 1, 2 }, 60 | { "BH1", 0, 1, 1, 3 }, 61 | 62 | { "BA2", 2, 4, 0, 1 }, 63 | { "BB2", 2, 5, 0, 1 }, 64 | { "BC2", 2, 6, 0, 1 }, 65 | { "BD2", 2, 7, 0, 1 }, 66 | { "BE2", 1, 0, 0, 1 }, 67 | { "BF2", 1, 1, 0, 1 }, 68 | { "BG2", 1, 2, 0, 1 }, 69 | { "BH2", 1, 3, 0, 1 }, 70 | 71 | { "CA1", 0, 2, 2, 4 }, 72 | { "CB1", 0, 2, 2, 5 }, 73 | { "CC1", 0, 2, 2, 6 }, 74 | { "CD1", 0, 2, 2, 7 }, 75 | { "CE1", 0, 2, 1, 0 }, 76 | { "CF1", 0, 2, 1, 1 }, 77 | { "CG1", 0, 2, 1, 2 }, 78 | { "CH1", 0, 2, 1, 3 }, 79 | 80 | { "CA2", 2, 4, 0, 2 }, 81 | { "CB2", 2, 5, 0, 2 }, 82 | { "CC2", 2, 6, 0, 2 }, 83 | { "CD2", 2, 7, 0, 2 }, 84 | { "CE2", 1, 0, 0, 2 }, 85 | { "CF2", 1, 1, 0, 2 }, 86 | { "CG2", 1, 2, 0, 2 }, 87 | { "CH2", 1, 3, 0, 2 }, 88 | 89 | { "DA1", 0, 3, 2, 4 }, 90 | { "DB1", 0, 3, 2, 5 }, 91 | { "DC1", 0, 3, 2, 6 }, 92 | { "DD1", 0, 3, 2, 7 }, 93 | { "DE1", 0, 3, 1, 0 }, 94 | { "DF1", 0, 3, 1, 1 }, 95 | { "DG1", 0, 3, 1, 2 }, 96 | { "DH1", 0, 3, 1, 3 }, 97 | 98 | { "DA2", 2, 4, 0, 3 }, 99 | { "DB2", 2, 5, 0, 3 }, 100 | { "DC2", 2, 6, 0, 3 }, 101 | { "DD2", 2, 7, 0, 3 }, 102 | { "DE2", 1, 0, 0, 3 }, 103 | { "DF2", 1, 1, 0, 3 }, 104 | { "DG2", 1, 2, 0, 3 }, 105 | { "DH2", 1, 3, 0, 3 }, 106 | 107 | { "EA1", 0, 4, 2, 4 }, 108 | { "EB1", 0, 4, 2, 5 }, 109 | { "EC1", 0, 4, 2, 6 }, 110 | { "ED1", 0, 4, 2, 7 }, 111 | { "EE1", 0, 4, 1, 0 }, 112 | { "EF1", 0, 4, 1, 1 }, 113 | { "EG1", 0, 4, 1, 2 }, 114 | { "EH1", 0, 4, 1, 3 }, 115 | 116 | { "EA2", 2, 4, 0, 4 }, 117 | { "EB2", 2, 5, 0, 4 }, 118 | { "EC2", 2, 6, 0, 4 }, 119 | { "ED2", 2, 7, 0, 4 }, 120 | { "EE2", 1, 0, 0, 4 }, 121 | { "EF2", 1, 1, 0, 4 }, 122 | { "EG2", 1, 2, 0, 4 }, 123 | { "EH2", 1, 3, 0, 4 }, 124 | 125 | { "FA1", 0, 5, 2, 4 }, 126 | { "FB1", 0, 5, 2, 5 }, 127 | { "FC1", 0, 5, 2, 6 }, 128 | { "FD1", 0, 5, 2, 7 }, 129 | { "FE1", 0, 5, 1, 0 }, 130 | { "FF1", 0, 5, 1, 1 }, 131 | { "FG1", 0, 5, 1, 2 }, 132 | { "FH1", 0, 5, 1, 3 }, 133 | 134 | { "FA2", 2, 4, 0, 5 }, 135 | { "FB2", 2, 5, 0, 5 }, 136 | { "FC2", 2, 6, 0, 5 }, 137 | { "FD2", 2, 7, 0, 5 }, 138 | { "FE2", 1, 0, 0, 5 }, 139 | { "FF2", 1, 1, 0, 5 }, 140 | { "FG2", 1, 2, 0, 5 }, 141 | { "FH2", 1, 3, 0, 5 }, 142 | 143 | { "GA1", 0, 6, 2, 4 }, 144 | { "GB1", 0, 6, 2, 5 }, 145 | { "GC1", 0, 6, 2, 6 }, 146 | { "GD1", 0, 6, 2, 7 }, 147 | { "GE1", 0, 6, 1, 0 }, 148 | { "GF1", 0, 6, 1, 1 }, 149 | { "GG1", 0, 6, 1, 2 }, 150 | { "GH1", 0, 6, 1, 3 }, 151 | 152 | { "GA2", 2, 4, 0, 6 }, 153 | { "GB2", 2, 5, 0, 6 }, 154 | { "GC2", 2, 6, 0, 6 }, 155 | { "GD2", 2, 7, 0, 6 }, 156 | { "GE2", 1, 0, 0, 6 }, 157 | { "GF2", 1, 1, 0, 6 }, 158 | { "GG2", 1, 2, 0, 6 }, 159 | { "GH2", 1, 3, 0, 6 }, 160 | 161 | { "HA1", 0, 7, 2, 4 }, 162 | { "HB1", 0, 7, 2, 5 }, 163 | { "HC1", 0, 7, 2, 6 }, 164 | { "HD1", 0, 7, 2, 7 }, 165 | { "HE1", 0, 7, 1, 0 }, 166 | { "HF1", 0, 7, 1, 1 }, 167 | { "HG1", 0, 7, 1, 2 }, 168 | { "HH1", 0, 7, 1, 3 }, 169 | 170 | { "HA2", 2, 4, 0, 7 }, 171 | { "HB2", 2, 5, 0, 7 }, 172 | { "HC2", 2, 6, 0, 7 }, 173 | { "HD2", 2, 7, 0, 7 }, 174 | { "HE2", 1, 0, 0, 7 }, 175 | { "HF2", 1, 1, 0, 7 }, 176 | { "HG2", 1, 2, 0, 7 }, 177 | { "HH2", 1, 3, 0, 7 }, 178 | 179 | { NULL, 0, 0, 0, 0 } 180 | }; 181 | 182 | led_charlieplex_t led_analog_watch_v1 = { 183 | 0, 184 | led_analog_watch_v1_ports, 185 | led_analog_watch_v1_leds 186 | }; 187 | 188 | -------------------------------------------------------------------------------- /led_analog_clock/led_analog_watch_v1.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Jeremy Cole 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program 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. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | */ 19 | 20 | #ifndef LED_ANALOG_WATCH_V1_H 21 | #define LED_ANALOG_WATCH_V1_H 22 | 23 | #include 24 | 25 | led_charlieplex_t led_analog_watch_v1; 26 | 27 | #endif /* LED_ANALOG_WATCH_V1_H */ 28 | -------------------------------------------------------------------------------- /led_analog_clock/led_mapping.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Jeremy Cole 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program 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. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | */ 19 | 20 | /** 21 | * @file 22 | * 23 | * Mapping tables of all LEDs into logical positions. 24 | */ 25 | 26 | /** 27 | * Map of 60 LEDs in outer ring for minutes 28 | * A{A:H}1, B{A:G}1, C{A:H}1, D{A:G}1, E{A:H}1, F{A:G}1, G{A:H}1, H{A:G}1 29 | */ 30 | char *led_mapping_minute[60] = { 31 | "AA1", /* 00 */ 32 | "AB1", /* 01 */ 33 | "AC1", /* 02 */ 34 | "AD1", /* 03 */ 35 | "AE1", /* 04 */ 36 | "AF1", /* 05 */ 37 | "AG1", /* 06 */ 38 | "AH1", /* 07 */ 39 | "BA1", /* 08 */ 40 | "BB1", /* 09 */ 41 | "BC1", /* 10 */ 42 | "BD1", /* 11 */ 43 | "BE1", /* 12 */ 44 | "BF1", /* 13 */ 45 | "BG1", /* 14 */ 46 | 47 | "CA1", /* 15 */ 48 | "CB1", /* 16 */ 49 | "CC1", /* 17 */ 50 | "CD1", /* 18 */ 51 | "CE1", /* 19 */ 52 | "CF1", /* 20 */ 53 | "CG1", /* 21 */ 54 | "CH1", /* 22 */ 55 | "DA1", /* 23 */ 56 | "DB1", /* 24 */ 57 | "DC1", /* 25 */ 58 | "DD1", /* 26 */ 59 | "DE1", /* 27 */ 60 | "DF1", /* 28 */ 61 | "DG1", /* 29 */ 62 | 63 | "EA1", /* 30 */ 64 | "EB1", /* 31 */ 65 | "EC1", /* 32 */ 66 | "ED1", /* 33 */ 67 | "EE1", /* 34 */ 68 | "EF1", /* 35 */ 69 | "EG1", /* 36 */ 70 | "EH1", /* 37 */ 71 | "FA1", /* 38 */ 72 | "FB1", /* 39 */ 73 | "FC1", /* 40 */ 74 | "FD1", /* 41 */ 75 | "FE1", /* 42 */ 76 | "FF1", /* 43 */ 77 | "FG1", /* 44 */ 78 | 79 | "GA1", /* 45 */ 80 | "GB1", /* 46 */ 81 | "GC1", /* 47 */ 82 | "GD1", /* 48 */ 83 | "GE1", /* 49 */ 84 | "GF1", /* 50 */ 85 | "GG1", /* 51 */ 86 | "GH1", /* 52 */ 87 | "HA1", /* 53 */ 88 | "HB1", /* 54 */ 89 | "HC1", /* 55 */ 90 | "HD1", /* 56 */ 91 | "HE1", /* 57 */ 92 | "HF1", /* 58 */ 93 | "HG1", /* 59 */ 94 | }; 95 | 96 | /** 97 | * Map of 48 LEDs in inner ring for quarter hours 98 | * A{A:H}2, B{A:D}2, C{A:H}2, D{A:D}2, E{A:H}2, F{A:D}2, G{A:H}2, H{A:D}2 99 | */ 100 | char *led_mapping_qhour[48] = { 101 | "AA2", /* 00 */ 102 | "AB2", /* 01 */ 103 | "AC2", /* 02 */ 104 | "AD2", /* 03 */ 105 | 106 | "AE2", /* 04 */ 107 | "AF2", /* 05 */ 108 | "AG2", /* 06 */ 109 | "AH2", /* 07 */ 110 | 111 | "BA2", /* 08 */ 112 | "BB2", /* 09 */ 113 | "BC2", /* 10 */ 114 | "BD2", /* 11 */ 115 | 116 | "CA2", /* 12 */ 117 | "CB2", /* 13 */ 118 | "CC2", /* 14 */ 119 | "CD2", /* 15 */ 120 | 121 | "CE2", /* 16 */ 122 | "CF2", /* 17 */ 123 | "CG2", /* 18 */ 124 | "CH2", /* 19 */ 125 | 126 | "DA2", /* 20 */ 127 | "DB2", /* 21 */ 128 | "DC2", /* 22 */ 129 | "DD2", /* 23 */ 130 | 131 | "EA2", /* 24 */ 132 | "EB2", /* 25 */ 133 | "EC2", /* 26 */ 134 | "ED2", /* 27 */ 135 | 136 | "EE2", /* 28 */ 137 | "EF2", /* 29 */ 138 | "EG2", /* 30 */ 139 | "EH2", /* 31 */ 140 | 141 | "FA2", /* 32 */ 142 | "FB2", /* 33 */ 143 | "FC2", /* 34 */ 144 | "FD2", /* 35 */ 145 | 146 | "GA2", /* 36 */ 147 | "GB2", /* 37 */ 148 | "GC2", /* 38 */ 149 | "GD2", /* 39 */ 150 | 151 | "GE2", /* 40 */ 152 | "GF2", /* 41 */ 153 | "GG2", /* 42 */ 154 | "GH2", /* 43 */ 155 | 156 | "HA2", /* 44 */ 157 | "HB2", /* 45 */ 158 | "HC2", /* 46 */ 159 | "HD2", /* 47 */ 160 | }; 161 | 162 | /** 163 | * Map of 5 LEDs in bar at 0 degrees 164 | * B{E:H}2, BH1 165 | */ 166 | char *led_mapping_bar000[5] = { 167 | "BE2", /* 00 */ 168 | "BF2", /* 01 */ 169 | "BG2", /* 02 */ 170 | "BH2", /* 03 */ 171 | "BH1" /* 04 */ 172 | }; 173 | 174 | /** 175 | * Map of 5 LEDs in bar at 90 degrees 176 | * D{E:H}2, DH1 177 | */ 178 | char *led_mapping_bar090[5] = { 179 | "DE2", /* 00 */ 180 | "DF2", /* 01 */ 181 | "DG2", /* 02 */ 182 | "DH2", /* 03 */ 183 | "DH1" /* 04 */ 184 | }; 185 | 186 | /** 187 | * Map of 5 LEDs in bar at 180 degrees 188 | * F{E:H}2, FH1 189 | */ 190 | char *led_mapping_bar180[5] = { 191 | "FE2", /* 00 */ 192 | "FF2", /* 01 */ 193 | "FG2", /* 02 */ 194 | "FH2", /* 03 */ 195 | "FH1" /* 04 */ 196 | }; 197 | 198 | /** 199 | * Map of 5 LEDs in bar at 270 degrees 200 | * H{E:H}2, HH1 201 | */ 202 | char *led_mapping_bar270[5] = { 203 | "HE2", /* 00 */ 204 | "HF2", /* 01 */ 205 | "HG2", /* 02 */ 206 | "HH2", /* 03 */ 207 | "HH1", /* 04 */ 208 | }; 209 | 210 | /** 211 | * Map of all bars, iterating across 212 | */ 213 | char *led_mapping_across_all_bars[20] = { 214 | "BE2", /* 00 */ 215 | "BF2", /* 01 */ 216 | "BG2", /* 02 */ 217 | "BH2", /* 03 */ 218 | "BH1", /* 04 */ 219 | 220 | "DE2", /* 00 */ 221 | "DF2", /* 01 */ 222 | "DG2", /* 02 */ 223 | "DH2", /* 03 */ 224 | "DH1", /* 04 */ 225 | 226 | "FE2", /* 00 */ 227 | "FF2", /* 01 */ 228 | "FG2", /* 02 */ 229 | "FH2", /* 03 */ 230 | "FH1", /* 04 */ 231 | 232 | "HE2", /* 00 */ 233 | "HF2", /* 01 */ 234 | "HG2", /* 02 */ 235 | "HH2", /* 03 */ 236 | "HH1", /* 04 */ 237 | }; 238 | 239 | /** 240 | * Map of all bars, iterating around 241 | */ 242 | char *led_mapping_around_all_bars[20] = { 243 | "BE2", /* 00 */ 244 | "DE2", /* 00 */ 245 | "FE2", /* 00 */ 246 | "HE2", /* 00 */ 247 | 248 | "BF2", /* 01 */ 249 | "DF2", /* 01 */ 250 | "FF2", /* 01 */ 251 | "HF2", /* 01 */ 252 | 253 | "BG2", /* 02 */ 254 | "DG2", /* 02 */ 255 | "FG2", /* 02 */ 256 | "HG2", /* 02 */ 257 | 258 | "BH2", /* 03 */ 259 | "DH2", /* 03 */ 260 | "FH2", /* 03 */ 261 | "HH2", /* 03 */ 262 | 263 | "BH1", /* 04 */ 264 | "DH1", /* 04 */ 265 | "FH1", /* 04 */ 266 | "HH1", /* 04 */ 267 | }; 268 | 269 | /** 270 | * Innermost 4 LEDs in bars 271 | */ 272 | char *led_mapping_inner[4] = { 273 | "BH1", 274 | "DH1", 275 | "FH1", 276 | "HH1", 277 | }; 278 | -------------------------------------------------------------------------------- /led_analog_clock/led_mapping.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Jeremy Cole 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program 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. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | */ 19 | 20 | #ifndef LED_MAPPING_H 21 | #define LED_MAPPING_H 22 | 23 | extern char *led_mapping_minute[60]; 24 | extern char *led_mapping_qhour[48]; 25 | extern char *led_mapping_bar000[5]; 26 | extern char *led_mapping_bar090[5]; 27 | extern char *led_mapping_bar180[5]; 28 | extern char *led_mapping_bar270[5]; 29 | extern char *led_mapping_across_all_bars[20]; 30 | extern char *led_mapping_around_all_bars[20]; 31 | extern char *led_mapping_inner[4]; 32 | 33 | #endif /* LED_MAPPING_H */ 34 | -------------------------------------------------------------------------------- /led_charlieplex/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | led_charlieplex 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.cdt.managedbuilder.core.genmakebuilder 10 | clean,full,incremental, 11 | 12 | 13 | ?name? 14 | 15 | 16 | 17 | org.eclipse.cdt.make.core.append_environment 18 | true 19 | 20 | 21 | org.eclipse.cdt.make.core.autoBuildTarget 22 | all 23 | 24 | 25 | org.eclipse.cdt.make.core.buildArguments 26 | 27 | 28 | 29 | org.eclipse.cdt.make.core.buildCommand 30 | make 31 | 32 | 33 | org.eclipse.cdt.make.core.buildLocation 34 | ${workspace_loc:/led_charlieplex/Release} 35 | 36 | 37 | org.eclipse.cdt.make.core.cleanBuildTarget 38 | clean 39 | 40 | 41 | org.eclipse.cdt.make.core.contents 42 | org.eclipse.cdt.make.core.activeConfigSettings 43 | 44 | 45 | org.eclipse.cdt.make.core.enableAutoBuild 46 | false 47 | 48 | 49 | org.eclipse.cdt.make.core.enableCleanBuild 50 | true 51 | 52 | 53 | org.eclipse.cdt.make.core.enableFullBuild 54 | true 55 | 56 | 57 | org.eclipse.cdt.make.core.fullBuildTarget 58 | all 59 | 60 | 61 | org.eclipse.cdt.make.core.stopOnError 62 | true 63 | 64 | 65 | org.eclipse.cdt.make.core.useDefaultBuildCmd 66 | true 67 | 68 | 69 | 70 | 71 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder 72 | 73 | 74 | 75 | 76 | 77 | org.eclipse.cdt.core.cnature 78 | org.eclipse.cdt.managedbuilder.core.managedBuildNature 79 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature 80 | de.innot.avreclipse.core.avrnature 81 | 82 | 83 | -------------------------------------------------------------------------------- /led_charlieplex/.settings/de.innot.avreclipse.core.prefs: -------------------------------------------------------------------------------- 1 | avrtarget/ClockFrequency=8000000 2 | avrtarget/ExtRAMSize=0 3 | avrtarget/ExtendedRAM=false 4 | avrtarget/MCUType=atmega644 5 | avrtarget/UseEEPROM=false 6 | avrtarget/UseExtendedRAMforHeap=true 7 | avrtarget/de.innot.avreclipse.configuration.lib.release.541968731.51744801/ClockFrequency=8000000 8 | avrtarget/de.innot.avreclipse.configuration.lib.release.541968731.51744801/ExtRAMSize=0 9 | avrtarget/de.innot.avreclipse.configuration.lib.release.541968731.51744801/ExtendedRAM=false 10 | avrtarget/de.innot.avreclipse.configuration.lib.release.541968731.51744801/MCUType=atmega644 11 | avrtarget/de.innot.avreclipse.configuration.lib.release.541968731.51744801/UseEEPROM=false 12 | avrtarget/de.innot.avreclipse.configuration.lib.release.541968731.51744801/UseExtendedRAMforHeap=true 13 | avrtarget/perConfig=false 14 | eclipse.preferences.version=1 15 | -------------------------------------------------------------------------------- /led_charlieplex/led_charlieplex.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Jeremy Cole 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program 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. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | #include "led_charlieplex.h" 25 | 26 | void led_charlieplex_init(led_charlieplex_t *charlieplex) 27 | { 28 | led_charlieplex_port_t *port = charlieplex->port; 29 | 30 | for(; port->pins != 0x00; port++) 31 | { 32 | *(port->ddr) &= ~(port->pins); 33 | *(port->port) &= ~(port->pins); 34 | } 35 | } 36 | 37 | uint8_t led_charlieplex_find_index_by_name(led_charlieplex_t *charlieplex, char *name) 38 | { 39 | led_charlieplex_led_t *led = charlieplex->led; 40 | uint8_t index = 0; 41 | 42 | for(; led->name != NULL; led++, index++) 43 | { 44 | if(strcasecmp(led->name, name) == 0) 45 | return index; 46 | } 47 | 48 | return LED_CHARLIEPLEX_LED_UNKNOWN; 49 | } 50 | 51 | inline void led_charlieplex_unset(led_charlieplex_t *charlieplex, led_charlieplex_led_t *led) 52 | { 53 | *(charlieplex->port[led->h_port].ddr) &= ~_BV(led->h_value); 54 | *(charlieplex->port[led->l_port].ddr) &= ~_BV(led->l_value); 55 | 56 | *(charlieplex->port[led->h_port].port) &= ~_BV(led->h_value); 57 | *(charlieplex->port[led->l_port].port) &= ~_BV(led->l_value); 58 | } 59 | 60 | inline void led_charlieplex_unset_last_inline(led_charlieplex_t *charlieplex) 61 | { 62 | if(charlieplex->last_led) 63 | { 64 | led_charlieplex_unset(charlieplex, charlieplex->last_led); 65 | charlieplex->last_led = NULL; 66 | } 67 | } 68 | 69 | void led_charlieplex_unset_last(led_charlieplex_t *charlieplex) 70 | { 71 | led_charlieplex_unset_last_inline(charlieplex); 72 | } 73 | 74 | inline void led_charlieplex_set(led_charlieplex_t *charlieplex, led_charlieplex_led_t *led) 75 | { 76 | led_charlieplex_unset_last_inline(charlieplex); 77 | 78 | /* 79 | * Set the data direction registers so that unused pins for this LED 80 | * are not set as outputs. This will ensure that the pullups and 81 | * pulldowns for that pin are disabled 82 | */ 83 | *(charlieplex->port[led->h_port].ddr) |= _BV(led->h_value); 84 | *(charlieplex->port[led->l_port].ddr) |= _BV(led->l_value); 85 | 86 | /* 87 | * Enable the pullup on the high side of the LED and enable the pulldown 88 | * on the low side. 89 | */ 90 | *(charlieplex->port[led->h_port].port) |= _BV(led->h_value); 91 | *(charlieplex->port[led->l_port].port) &= ~_BV(led->l_value); 92 | 93 | /* Track the LED set so that it can be quickly unset later. */ 94 | charlieplex->last_led = led; 95 | } 96 | 97 | void led_charlieplex_set_by_name(led_charlieplex_t *charlieplex, char *name) 98 | { 99 | uint8_t led_index; 100 | 101 | led_index = led_charlieplex_find_index_by_name(charlieplex, name); 102 | 103 | if(led_index == LED_CHARLIEPLEX_LED_UNKNOWN) 104 | return; 105 | 106 | led_charlieplex_set(charlieplex, &charlieplex->led[led_index]); 107 | } 108 | 109 | void led_charlieplex_set_by_index(led_charlieplex_t *charlieplex, uint8_t index) 110 | { 111 | led_charlieplex_set(charlieplex, &charlieplex->led[index]); 112 | } 113 | -------------------------------------------------------------------------------- /led_charlieplex/led_charlieplex.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Jeremy Cole 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program 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. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | */ 19 | 20 | /** 21 | 22 | @mainpage 23 | 24 | A library to handle a charlieplexed matrix of LEDs. 25 | 26 | @section about About Charliplexing 27 | 28 | Charlieplexing is a technique used to allow a large number of LEDs to be 29 | used in a matrix display, while only using a small number of IO pins. It 30 | depends on tri-state logic to allow pins to "float". 31 | 32 | A charlieplexed display is arranged in an X-Y matrix of cells as typical, 33 | but each cell contains two LEDs in opposite polarities as follows: 34 | 35 | @verbatim 36 | X Y 37 | | | 38 | +-->|--+ (a) 39 | +--|<--+ (b) 40 | @endverbatim 41 | 42 | Due to LEDs being polarized one pin is pulled high and the other is pulled 43 | low, one of the two LEDs will light. When these cells are used in this way, 44 | a 4x4 matrix could be constructed as follows: 45 | 46 | @verbatim 47 | X0 X1 X2 X3 48 | ---- ---- ---- ---- 49 | Y0 | x0y0 x1y0 x2y0 x3y0 50 | Y1 | x0y1 x1y1 x2y1 x3y1 51 | Y2 | x0y2 x1y2 x2y2 x3y2 52 | Y3 | x0y3 x1y3 x2y3 x3y3 53 | @endverbatim 54 | 55 | If X0 is pulled high and Y0 is pulled low while X{1-3} and Y{1-3} are allowed 56 | to float (tri-stated), only x0y0a will light. In order to minimize ghosting 57 | and other display artifacts, only one LED can be lit at a time. 58 | 59 | If a high enough refresh rate can be maintained, a charlieplexed display (as 60 | any other LED display) can appear as though several LEDs are lit simultaneously. 61 | 62 | More information can be found on Wikipedia: 63 | 64 | http://en.wikipedia.org/wiki/Charlieplexing 65 | 66 | @section usage Use of this library 67 | 68 | Typically you will want to populate a led_charlieplex_t structure 69 | representing your charlieplexed matrix. Usually it is easiest to do this 70 | in three steps by creating and populating the sub-structures first. For 71 | example, using the previous 4x4 matrix, with: 72 | 73 | @li \c X{0-3} connected to \c PB{0-3} 74 | @li \c Y{0-3} connected to \c PD{4-7} 75 | 76 | The led_charlieplex_port_t would be populated as follows: 77 | 78 | @code 79 | led_charlieplex_port_t led_example_ports[] = { 80 | { &PINB, &DDRB, &PORTB, (_BV(PB0) | _BV(PB1) | _BV(PB2) | _BV(PB3)) }, 81 | { &PIND, &DDRD, &PORTD, (_BV(PD4) | _BV(PD5) | _BV(PD6) | _BV(PD7)) }, 82 | { NULL, NULL, NULL, 0 }, 83 | }; 84 | @endcode 85 | 86 | The led_charlieplex_led_t would be populated as follows: 87 | 88 | @code 89 | led_charlieplex_led_t led_example_leds[] = { 90 | { "x0y0a", 0, 0, 1, 4 }, 91 | { "x1y0a", 0, 1, 1, 4 }, 92 | { "x2y0a", 0, 2, 1, 4 }, 93 | { "x3y0a", 0, 3, 1, 4 }, 94 | 95 | { "x0y0b", 1, 4, 0, 0 }, 96 | { "x1y0b", 1, 4, 0, 1 }, 97 | { "x2y0b", 1, 4, 0, 2 }, 98 | { "x3y0b", 1, 4, 0, 3 }, 99 | 100 | ... 101 | 102 | { "x0y1a", 0, 0, 1, 5 }, 103 | { "x1y1a", 0, 1, 1, 5 }, 104 | { "x2y1a", 0, 2, 1, 5 }, 105 | { "x3y1a", 0, 3, 1, 5 }, 106 | 107 | { "x0y1b", 1, 5, 0, 0 }, 108 | { "x1y1b", 1, 5, 0, 1 }, 109 | { "x2y1b", 1, 5, 0, 2 }, 110 | { "x3y1b", 1, 5, 0, 3 }, 111 | 112 | ... 113 | 114 | { NULL, 0, 0, 0, 0 } 115 | }; 116 | @endcode 117 | 118 | And then the led_charlieplex_t would be populated by referencing both supporting 119 | structures as follows: 120 | 121 | @code 122 | led_charlieplex_t led_example = { 123 | 0, 124 | led_example_ports, 125 | led_example_leds 126 | }; 127 | @endcode 128 | 129 | */ 130 | 131 | #ifndef LED_CHARLIEPLEX_H 132 | #define LED_CHARLIEPLEX_H 133 | 134 | /** 135 | * A special value meaning that no LED was found, returned where an index 136 | * would otherwise be returned. This limits the maximum number of LEDs in a 137 | * matrix to 254, as index 255 is hereby reserved. 138 | */ 139 | #define LED_CHARLIEPLEX_LED_UNKNOWN 0xff 140 | 141 | /** 142 | * A structure used to contain the PIN*, DDR*, PORT* and a bitmap of pins 143 | * in use on a single port used for this charlieplexed matrix. 144 | */ 145 | typedef struct _led_charlieplex_port_t 146 | { 147 | volatile uint8_t *pin; /**< The PIN* for this port, e.g. &PINC. */ 148 | volatile uint8_t *ddr; /**< The DDR* for this port, e.g. &DDRC. */ 149 | volatile uint8_t *port; /**< The PORT* for this port, e.g. &PORTC. */ 150 | volatile uint8_t pins; /**< The pins in use for this display, e.g. (_BV(PC0) & _BV(PC1)) or 0xFF. */ 151 | } led_charlieplex_port_t; 152 | 153 | /** 154 | * A structure used to contain all pins name, and high and low pin information. 155 | * 156 | * The h_port and l_port members are indexes into the display's ->port array. 157 | * 158 | * The h_value and l_value members are the pin number (0-7) of the pin on the 159 | * associated port. It is expanded later in all calculations as necessary. 160 | */ 161 | typedef struct _led_charlieplex_led_t 162 | { 163 | char *name; /**< The name of this LED, preferably short, e.g. "AA1". */ 164 | uint8_t h_port:4; /**< The high (+) port index, e.g. 0. */ 165 | uint8_t h_value:4; /**< The high (+) pin number, e.g. 1. */ 166 | uint8_t l_port:4; /**< The low (GND) port index, e.g. 1. */ 167 | uint8_t l_value:4; /**< The low (GND) pin number, e.g. 2. */ 168 | } led_charlieplex_led_t; 169 | 170 | /** 171 | * A structure used to contain information about a charlieplexed matrix. 172 | */ 173 | typedef struct _led_charlieplex_t 174 | { 175 | uint8_t dummy; 176 | 177 | /** 178 | * A NULL-terminated array of pointers to led_charlieplex_port_t structures 179 | * representing all of the ports in use for this charlieplexed matrix. 180 | */ 181 | led_charlieplex_port_t *port; 182 | 183 | /** 184 | * A NULL-terminated array of pointers to led_charlieplex_led_t structures 185 | * representing the names and positions of all LEDs present in this charlie- 186 | * plexed matrix. 187 | */ 188 | led_charlieplex_led_t *led; 189 | 190 | /** 191 | * (Internal use only.) A pointer to the last LED enabled, so that it can be 192 | * efficiently toggled off without affecting the rest of the matrix. 193 | */ 194 | led_charlieplex_led_t *last_led; 195 | } led_charlieplex_t; 196 | 197 | /** 198 | * Initialize a charlieplexed matrix, clearing all LEDs. 199 | */ 200 | extern void led_charlieplex_init(led_charlieplex_t *charlieplex); 201 | 202 | /** 203 | * Find the index into the led_charlieplex_t.led structure for led. 204 | * 205 | * @param[in] charlieplex A pointer to the led_charlieplex_t structure. 206 | * @param[in] name The name of the LED to search for. 207 | * 208 | * @return The index of the LED, if found, or LED_CHARLIEPLEX_LED_UNKNOWN if not found. 209 | */ 210 | extern uint8_t led_charlieplex_find_index_by_name(led_charlieplex_t *charlieplex, char *name); 211 | 212 | /** 213 | * Set (enable) an LED by name. 214 | * 215 | * @param[in] charlieplex A pointer to the led_charlieplex_t structure. 216 | * @param[in] name The name of the LED to set. 217 | */ 218 | extern void led_charlieplex_set_by_name(led_charlieplex_t *charlieplex, char *name); 219 | 220 | /** 221 | * Set (enable) an LED by index in the led_charlieplex_t.led array. 222 | * 223 | * @param[in] charlieplex A pointer to the led_charlieplex_t structure. 224 | * @param[in] index The index of the LED to set. 225 | */ 226 | extern void led_charlieplex_set_by_index(led_charlieplex_t *charlieplex, uint8_t index); 227 | 228 | /** 229 | * Unset (disable) the last LED set, clearing the matrix. 230 | * 231 | * @param[in] charlieplex A pointer to the led_charlieplex_t structure. 232 | */ 233 | extern void led_charlieplex_unset_last(led_charlieplex_t *charlieplex); 234 | 235 | #endif /* LED_CHARLIEPLEX_H */ 236 | -------------------------------------------------------------------------------- /led_sequencer/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | led_sequencer 4 | 5 | 6 | led_charlieplex 7 | 8 | 9 | 10 | org.eclipse.cdt.managedbuilder.core.genmakebuilder 11 | clean,full,incremental, 12 | 13 | 14 | ?name? 15 | 16 | 17 | 18 | org.eclipse.cdt.make.core.append_environment 19 | true 20 | 21 | 22 | org.eclipse.cdt.make.core.autoBuildTarget 23 | all 24 | 25 | 26 | org.eclipse.cdt.make.core.buildArguments 27 | 28 | 29 | 30 | org.eclipse.cdt.make.core.buildCommand 31 | make 32 | 33 | 34 | org.eclipse.cdt.make.core.buildLocation 35 | ${workspace_loc:/led_sequencer/Release} 36 | 37 | 38 | org.eclipse.cdt.make.core.cleanBuildTarget 39 | clean 40 | 41 | 42 | org.eclipse.cdt.make.core.contents 43 | org.eclipse.cdt.make.core.activeConfigSettings 44 | 45 | 46 | org.eclipse.cdt.make.core.enableAutoBuild 47 | false 48 | 49 | 50 | org.eclipse.cdt.make.core.enableCleanBuild 51 | true 52 | 53 | 54 | org.eclipse.cdt.make.core.enableFullBuild 55 | true 56 | 57 | 58 | org.eclipse.cdt.make.core.fullBuildTarget 59 | all 60 | 61 | 62 | org.eclipse.cdt.make.core.stopOnError 63 | true 64 | 65 | 66 | org.eclipse.cdt.make.core.useDefaultBuildCmd 67 | true 68 | 69 | 70 | 71 | 72 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder 73 | 74 | 75 | 76 | 77 | 78 | org.eclipse.cdt.core.cnature 79 | org.eclipse.cdt.managedbuilder.core.managedBuildNature 80 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature 81 | de.innot.avreclipse.core.avrnature 82 | 83 | 84 | -------------------------------------------------------------------------------- /led_sequencer/.settings/de.innot.avreclipse.core.prefs: -------------------------------------------------------------------------------- 1 | avrtarget/ClockFrequency=8000000 2 | avrtarget/ExtRAMSize=0 3 | avrtarget/ExtendedRAM=false 4 | avrtarget/MCUType=atmega644 5 | avrtarget/UseEEPROM=false 6 | avrtarget/UseExtendedRAMforHeap=true 7 | avrtarget/de.innot.avreclipse.configuration.lib.release.1214275602.1933955972/ClockFrequency=8000000 8 | avrtarget/de.innot.avreclipse.configuration.lib.release.1214275602.1933955972/ExtRAMSize=0 9 | avrtarget/de.innot.avreclipse.configuration.lib.release.1214275602.1933955972/ExtendedRAM=false 10 | avrtarget/de.innot.avreclipse.configuration.lib.release.1214275602.1933955972/MCUType=atmega644 11 | avrtarget/de.innot.avreclipse.configuration.lib.release.1214275602.1933955972/UseEEPROM=false 12 | avrtarget/de.innot.avreclipse.configuration.lib.release.1214275602.1933955972/UseExtendedRAMforHeap=true 13 | avrtarget/perConfig=false 14 | eclipse.preferences.version=1 15 | -------------------------------------------------------------------------------- /led_sequencer/led_sequencer.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Jeremy Cole 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program 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. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include 30 | 31 | #include "led_sequencer.h" 32 | 33 | led_sequencer_t *sequencer_global = NULL; 34 | 35 | /** 36 | * Dump the current animation sequence as a series of Sequence and Step lines 37 | * using printf. This is used only for debugging (mostly debugging the this 38 | * library itself). 39 | */ 40 | void led_sequencer_dump_sequence() 41 | { 42 | led_sequence_t *sequence; 43 | led_sequence_step_t *step; 44 | 45 | for(sequence = sequencer_global->sequence; sequence; sequence = sequence->next) 46 | { 47 | printf_P(PSTR("Sequence 0x%04x, %s\n"), 48 | (uint16_t)sequence, sequence->name); 49 | for(step = sequence->step; step; step = step->next) 50 | { 51 | printf_P(PSTR(" Step 0x%04x, JIT 0x%04x, %i ticks\n"), 52 | (uint16_t)step, (uint16_t)step->jit_function, step->ticks_remaining); 53 | } 54 | } 55 | } 56 | 57 | /** 58 | * Interrupt handler for "tick" interrupt set up by led_sequencer_timer_init(). 59 | */ 60 | ISR(TIMER0_COMPA_vect) 61 | { 62 | led_sequencer_tick(); 63 | } 64 | 65 | /** 66 | * Initialize Timer 0 to fire "hz" times per second. 67 | */ 68 | void led_sequencer_timer_init(uint16_t hz) 69 | { 70 | /* Set pre-scaler to /256 */ 71 | TCCR0B |= _BV(CS02); 72 | 73 | /* Force Output Compare A */ 74 | TCCR0B |= _BV(FOC0A); 75 | 76 | /* Output Compare Interrupt Enable A */ 77 | TIMSK0 |= _BV(OCIE0A); 78 | 79 | /* Set initial counter value */ 80 | TCNT0 = 0; 81 | 82 | /* Set Output Compare Register to aim for 1ms interrupt */ 83 | OCR0A = (F_CPU / 256) / hz ; 84 | } 85 | 86 | /** 87 | * Initialize the sequencer library, including the timer and memory structures. 88 | */ 89 | led_sequencer_t *led_sequencer_init(uint16_t hz) 90 | { 91 | sequencer_global = malloc(sizeof(led_sequencer_t)); 92 | 93 | led_sequencer_timer_init(hz); 94 | 95 | sequencer_global->matrix = NULL; 96 | sequencer_global->sequence = NULL; 97 | sequencer_global->status = LED_SEQUENCER_HALTED; 98 | 99 | return sequencer_global; 100 | } 101 | 102 | void led_sequencer_halt() 103 | { 104 | if(sequencer_global) 105 | sequencer_global->status = LED_SEQUENCER_HALTED; 106 | } 107 | 108 | void led_sequencer_run() 109 | { 110 | if(sequencer_global) 111 | sequencer_global->status = LED_SEQUENCER_RUNNING; 112 | } 113 | 114 | /** 115 | * For a given sequence step, if ticks_remaining has reached zero, free 116 | * the step. Then, if the current step isn't perpetual, subtract a tick 117 | * from the step's ticks_remaining. 118 | */ 119 | void led_sequencer_tick_sequence_step(led_sequence_t *sequence) 120 | { 121 | led_sequence_step_t *free_step; 122 | 123 | if(sequence->step->ticks_remaining == 0) 124 | { 125 | if(sequence->step->jit_function 126 | && ((*sequence->step->jit_function)(sequence->step, LED_SEQUENCER_JIT_EMPTY) == LED_SEQUENCER_JIT_CONTINUE) 127 | && (sequence->step->ticks_remaining > 0)) 128 | goto refilled; 129 | 130 | free_step = sequence->step; 131 | sequence->step = sequence->step->next; 132 | free(free_step); 133 | 134 | if(sequence->step && sequence->step->jit_function) 135 | (*sequence->step->jit_function)(sequence->step, LED_SEQUENCER_JIT_INITIAL); 136 | } 137 | 138 | refilled: 139 | if(sequence->step && sequence->step->ticks_remaining != 0 && sequence->step->ticks_remaining != 0xff) 140 | { 141 | sequence->step->ticks_remaining--; 142 | } 143 | } 144 | 145 | /** 146 | * Iterate through all sequences in the global sequence list, for each of them, 147 | * call led_sequencer_tick_sequence_step. 148 | */ 149 | void led_sequencer_tick_sequence() 150 | { 151 | led_sequence_t *sequence; 152 | uint8_t sequence_steps = 0; 153 | 154 | for(sequence = sequencer_global->sequence; sequence; sequence = sequence->next) 155 | { 156 | if(sequence->step != NULL) 157 | { 158 | led_sequencer_tick_sequence_step(sequence); 159 | sequence_steps++; 160 | } 161 | } 162 | } 163 | 164 | /** 165 | * Progress the animation sequence by one tick, often 1ms, but depends on 166 | * the value 'hz' passed to led_sequencer_init(). Normally called by the 167 | * Timer 0 Output Compare A interrupt (TIMER0_COMPA_vect). This function 168 | * really just does the housekeeping and sanity checking and then calls out 169 | * to led_sequencer_tick_sequence() to do the real work. 170 | */ 171 | void led_sequencer_tick() 172 | { 173 | TCNT0 = 0; 174 | 175 | if(sequencer_global && sequencer_global->status == LED_SEQUENCER_RUNNING) 176 | { 177 | led_sequencer_tick_sequence(); 178 | } 179 | } 180 | 181 | /** 182 | * Play through one cycle of the LEDs which should currently be illuminated. 183 | * Normally this function is called during all spare time in the main loop, 184 | * and most other functions are called between runs of led_sequencer_run() or 185 | * through interrupts. 186 | */ 187 | void led_sequencer_display() 188 | { 189 | led_sequence_t *sequence; 190 | 191 | if(sequencer_global->status != LED_SEQUENCER_RUNNING) 192 | return; 193 | 194 | for(sequence = sequencer_global->sequence; sequence; sequence = sequence->next) 195 | { 196 | if(sequence->step && sequence->step->type == LED_SEQUENCER_STEP_SHOW) 197 | { 198 | led_charlieplex_set_by_index(sequence->step->matrix->charlieplex, sequence->step->matrix_index); 199 | _delay_us(20); 200 | led_charlieplex_unset_last(sequence->step->matrix->charlieplex); 201 | } 202 | } 203 | 204 | } 205 | 206 | /** 207 | * Find a matrix in the global matrix list by its name. 208 | */ 209 | led_matrix_t *led_sequencer_find_matrix_by_name(char *matrix_name) 210 | { 211 | led_matrix_t *matrix = sequencer_global->matrix; 212 | 213 | for(; matrix != NULL; matrix = matrix->next) 214 | { 215 | if(strcmp(matrix->name, matrix_name) == 0) 216 | return matrix; 217 | } 218 | 219 | return NULL; 220 | } 221 | 222 | /** 223 | * Push a matrix to the global matrix list. 224 | */ 225 | led_matrix_t *led_sequencer_push_front_matrix(char *matrix_name, led_charlieplex_t *charlieplex) 226 | { 227 | led_matrix_t *matrix; 228 | 229 | if((matrix = malloc(sizeof(led_matrix_t)))) 230 | { 231 | matrix->name = malloc(strlen(matrix_name)+1); 232 | strcpy(matrix->name, matrix_name); 233 | matrix->charlieplex = charlieplex; 234 | matrix->next = sequencer_global->matrix; 235 | sequencer_global->matrix = matrix; 236 | } 237 | 238 | return matrix; 239 | } 240 | 241 | /** 242 | * Find a sequence in the global sequence list by name. 243 | */ 244 | led_sequence_t *led_sequencer_find_sequence_by_name(char *sequence_name) 245 | { 246 | led_sequence_t *sequence = sequencer_global->sequence; 247 | 248 | for(; sequence != NULL; sequence = sequence->next) 249 | { 250 | if(strcmp(sequence->name, sequence_name) == 0) 251 | return sequence; 252 | } 253 | 254 | return NULL; 255 | } 256 | 257 | /** 258 | * Add a sequence to the global sequence list, and return a pointer to it. 259 | */ 260 | led_sequence_t *led_sequencer_push_back_sequence(char *sequence_name) 261 | { 262 | led_sequence_t *sequence, *last_sequence; 263 | 264 | if((sequence = malloc(sizeof(led_sequence_t)))) 265 | { 266 | sequence->name = malloc(strlen(sequence_name)+1); 267 | strcpy(sequence->name, sequence_name); 268 | sequence->step = NULL; 269 | sequence->next = NULL; 270 | } 271 | 272 | if(sequencer_global->sequence) 273 | { 274 | for(last_sequence = sequencer_global->sequence; last_sequence->next; last_sequence = last_sequence->next); 275 | last_sequence->next = sequence; 276 | } 277 | else 278 | { 279 | sequencer_global->sequence = sequence; 280 | } 281 | 282 | return sequence; 283 | } 284 | 285 | void led_sequencer_sequence_push_back_jit(char *sequence_name, led_sequence_step_type_t type, char *matrix_name, led_sequencer_jit_function_t *jit_function) 286 | { 287 | led_sequence_step_t *step; 288 | step = led_sequencer_sequence_push_back_step(sequence_name, type, matrix_name, NULL, 254); 289 | step->jit_function = jit_function; 290 | (*step->jit_function)(step, LED_SEQUENCER_JIT_INITIAL); 291 | } 292 | 293 | /** 294 | * Push a step on to the end of a sequence. 295 | */ 296 | led_sequence_step_t *led_sequencer_sequence_push_back_step(char *sequence_name, led_sequence_step_type_t type, char *matrix_name, char *led_name, uint8_t ticks) 297 | { 298 | led_sequence_t *sequence; 299 | led_sequence_step_t *step, *last_step; 300 | 301 | if((step = malloc(sizeof(led_sequence_step_t)))) 302 | { 303 | sequence = led_sequencer_find_sequence_by_name(sequence_name); 304 | 305 | step->type = type; 306 | step->matrix = led_sequencer_find_matrix_by_name(matrix_name); 307 | if(led_name) 308 | { 309 | step->matrix_index = led_charlieplex_find_index_by_name(step->matrix->charlieplex, led_name); 310 | } 311 | step->ticks_remaining = ticks; 312 | step->next = NULL; 313 | 314 | if(sequence->step) 315 | { 316 | for(last_step = sequence->step; last_step->next; last_step = last_step->next) {} 317 | last_step->next = step; 318 | } 319 | else 320 | { 321 | sequence->step = step; 322 | } 323 | 324 | return step; 325 | } 326 | 327 | return NULL; 328 | } 329 | 330 | /** 331 | * Modify a step in place within a sequence. This is mostly useful for steps 332 | * with a 'ticks' value of 255 (never ending). 333 | */ 334 | void led_sequencer_sequence_modify_step(led_sequence_step_t *step, char *led_name, uint8_t ticks) 335 | { 336 | step->matrix_index = led_charlieplex_find_index_by_name(step->matrix->charlieplex, led_name); 337 | step->ticks_remaining = ticks; 338 | } 339 | 340 | /** 341 | * Clear an entire sequence of any steps remaining. 342 | */ 343 | void led_sequencer_sequence_clear(char *sequence_name) 344 | { 345 | led_sequence_t *sequence; 346 | 347 | sequence = led_sequencer_find_sequence_by_name(sequence_name); 348 | 349 | for(; sequence->step; sequence->step = sequence->step->next) 350 | { 351 | free(sequence->step); 352 | } 353 | } 354 | -------------------------------------------------------------------------------- /led_sequencer/led_sequencer.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Jeremy Cole 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program 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. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | */ 19 | 20 | /* 21 | 22 | Sequence 0 23 | Step 0 24 | type 25 | matrix, matrix_index 26 | ticks_remaining 27 | next 28 | ... 29 | Step N 30 | NULL 31 | ... 32 | Sequence N 33 | NULL 34 | 35 | */ 36 | 37 | #ifndef LED_SEQUENCER_H 38 | #define LED_SEQUENCER_H 39 | 40 | #include 41 | 42 | #include 43 | 44 | /** 45 | * An LED matrix registered by name with the led_sequencer library. 46 | * Currently this only support the led_charlieplex library, but in the future 47 | * this should be extended to work with some others, in which case the main 48 | * charlieplex pointer will be renamed and changed to a void *. 49 | */ 50 | typedef struct _led_matrix_t 51 | { 52 | char *name; 53 | led_charlieplex_t *charlieplex; 54 | struct _led_matrix_t *next; 55 | } led_matrix_t; 56 | 57 | /** 58 | * Different types of steps, which primarily allows for inserting blank delays 59 | * into sequences. 60 | */ 61 | typedef enum _led_sequence_step_type_t 62 | { 63 | LED_SEQUENCER_STEP_DELAY_MS, 64 | LED_SEQUENCER_STEP_SHOW, 65 | LED_SEQUENCER_STEP_UNKNOWN = 255 66 | } led_sequence_step_type_t; 67 | 68 | 69 | #define LED_SEQUENCER_JIT_CONTINUE 1 70 | #define LED_SEQUENCER_JIT_DEQUEUE 2 71 | #define LED_SEQUENCER_JIT_INITIAL 100 72 | #define LED_SEQUENCER_JIT_EMPTY 101 73 | #define LED_SEQUENCER_JIT_ERROR 255 74 | 75 | //typedef struct _led_sequence_step_t; 76 | struct _led_sequence_step_t; 77 | typedef uint8_t (led_sequencer_jit_function_t)(struct _led_sequence_step_t *step, uint8_t status) ; 78 | 79 | /** 80 | * A single step and structure for singly linked list of steps within a 81 | * sequence. Each step is executed for 'ticks_remaining' ticks of the global 82 | * sequencer clock. 83 | */ 84 | typedef struct _led_sequence_step_t 85 | { 86 | led_sequence_step_type_t type; 87 | led_matrix_t *matrix; 88 | uint8_t matrix_index; 89 | uint8_t ticks_remaining; 90 | led_sequencer_jit_function_t *jit_function; 91 | struct _led_sequence_step_t *next; 92 | } led_sequence_step_t; 93 | 94 | /** 95 | * A sequence, registered by name and containing a singly linked list of 96 | * sequencer steps. 97 | */ 98 | typedef struct _led_sequence_t 99 | { 100 | char *name; 101 | led_sequence_step_t *step; 102 | struct _led_sequence_t *next; 103 | } led_sequence_t; 104 | 105 | typedef enum _led_sequencer_status_t 106 | { 107 | LED_SEQUENCER_HALTED = 0, 108 | LED_SEQUENCER_RUNNING = 1, 109 | } led_sequencer_status_t; 110 | 111 | /** 112 | * A global structure containing the two main items: all registered matrixes 113 | * and all registered sequences. Due to its manipulation within ISRs, this 114 | * is only really useful as a global. 115 | */ 116 | typedef struct _led_sequencer_t 117 | { 118 | led_matrix_t *matrix; 119 | led_sequence_t *sequence; 120 | led_sequencer_status_t status; 121 | } led_sequencer_t; 122 | 123 | /** 124 | * A global structure holding all sequencer-related data. 125 | */ 126 | extern led_sequencer_t *sequencer_global; 127 | 128 | extern led_sequencer_t *led_sequencer_init(uint16_t hz); 129 | 130 | extern void led_sequencer_halt(); 131 | extern void led_sequencer_run(); 132 | 133 | extern void led_sequencer_tick(); 134 | extern void led_sequencer_display(); 135 | extern void led_sequencer_dump_sequence(); 136 | extern void led_sequencer_timer_init(uint16_t hz); 137 | 138 | extern led_matrix_t *led_sequencer_find_matrix_by_name(char *matrix_name); 139 | extern led_matrix_t *led_sequencer_push_front_matrix(char *matrix_name, led_charlieplex_t *charlieplex); 140 | 141 | extern led_sequence_t *led_sequencer_find_sequence_by_name(char *sequence_name); 142 | extern led_sequence_t *led_sequencer_push_back_sequence(char *sequence_name); 143 | extern void led_sequencer_sequence_push_back_jit(char *sequence_name, led_sequence_step_type_t type, char *matrix_name, led_sequencer_jit_function_t *jit_function); 144 | extern led_sequence_step_t *led_sequencer_sequence_push_back_step(char *sequence_name, led_sequence_step_type_t type, char *matrix_name, char *led_name, uint8_t ticks); 145 | extern void led_sequencer_sequence_modify_step(led_sequence_step_t *step, char *led_name, uint8_t ticks); 146 | extern void led_sequencer_sequence_clear(char *sequence_name); 147 | 148 | #endif /* LED_SEQUENCER_H */ 149 | -------------------------------------------------------------------------------- /nmea/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | nmea 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.cdt.managedbuilder.core.genmakebuilder 10 | clean,full,incremental, 11 | 12 | 13 | 14 | 15 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder 16 | full,incremental, 17 | 18 | 19 | 20 | 21 | 22 | org.eclipse.cdt.core.cnature 23 | org.eclipse.cdt.managedbuilder.core.managedBuildNature 24 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature 25 | de.innot.avreclipse.core.avrnature 26 | 27 | 28 | -------------------------------------------------------------------------------- /nmea/.settings/de.innot.avreclipse.core.prefs: -------------------------------------------------------------------------------- 1 | avrtarget/ClockFrequency=8000000 2 | avrtarget/ExtRAMSize=0 3 | avrtarget/ExtendedRAM=false 4 | avrtarget/MCUType=atmega644 5 | avrtarget/UseEEPROM=false 6 | avrtarget/UseExtendedRAMforHeap=true 7 | avrtarget/de.innot.avreclipse.configuration.lib.release.2123079960.1021803781.939001143/ClockFrequency=8000000 8 | avrtarget/de.innot.avreclipse.configuration.lib.release.2123079960.1021803781.939001143/ExtRAMSize=0 9 | avrtarget/de.innot.avreclipse.configuration.lib.release.2123079960.1021803781.939001143/ExtendedRAM=false 10 | avrtarget/de.innot.avreclipse.configuration.lib.release.2123079960.1021803781.939001143/MCUType=atmega1284p 11 | avrtarget/de.innot.avreclipse.configuration.lib.release.2123079960.1021803781.939001143/UseEEPROM=false 12 | avrtarget/de.innot.avreclipse.configuration.lib.release.2123079960.1021803781.939001143/UseExtendedRAMforHeap=true 13 | avrtarget/de.innot.avreclipse.configuration.lib.release.2123079960.1021803781/ClockFrequency=8000000 14 | avrtarget/de.innot.avreclipse.configuration.lib.release.2123079960.1021803781/ExtRAMSize=0 15 | avrtarget/de.innot.avreclipse.configuration.lib.release.2123079960.1021803781/ExtendedRAM=false 16 | avrtarget/de.innot.avreclipse.configuration.lib.release.2123079960.1021803781/MCUType=atmega644 17 | avrtarget/de.innot.avreclipse.configuration.lib.release.2123079960.1021803781/UseEEPROM=false 18 | avrtarget/de.innot.avreclipse.configuration.lib.release.2123079960.1021803781/UseExtendedRAMforHeap=true 19 | avrtarget/perConfig=true 20 | eclipse.preferences.version=1 21 | -------------------------------------------------------------------------------- /nmea/nmea.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015, Jeremy Cole 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program 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. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | */ 19 | 20 | #ifndef NMEA_H_ 21 | #define NMEA_H_ 22 | 23 | #include 24 | 25 | #define NMEA_EPOCH 80 26 | 27 | #define NMEA_INVALID_TYPE 0x0001 28 | #define NMEA_INVALID_SENTENCE 0x0002 29 | #define NMEA_INVALID_TIME 0x0004 30 | #define NMEA_INVALID_DATE 0x0008 31 | #define NMEA_INVALID_LATITUDE 0x0010 32 | #define NMEA_INVALID_LONGITUDE 0x0020 33 | #define NMEA_INVALID_UNIT 0x2000 34 | #define NMEA_INVALID_STATUS 0x4000 35 | #define NMEA_INVALID_CHECKSUM 0x8000 36 | 37 | typedef struct _nmea_date_t 38 | { 39 | uint16_t year; 40 | uint8_t month; 41 | uint8_t day; 42 | } nmea_date_t; 43 | 44 | typedef struct _nmea_time_t 45 | { 46 | uint8_t hour; 47 | uint8_t minute; 48 | uint8_t second; 49 | uint16_t millisecond; 50 | } nmea_time_t; 51 | 52 | typedef struct _nmea_position_t 53 | { 54 | float latitude; 55 | float longitude; 56 | } nmea_position_t; 57 | 58 | typedef struct _nmea_velocity_t 59 | { 60 | float speed; 61 | float heading; 62 | } nmea_velocity_t; 63 | 64 | typedef struct _nmea_gprmc_t 65 | { 66 | char status; 67 | char mode; 68 | nmea_date_t date; 69 | nmea_time_t time; 70 | nmea_position_t position; 71 | nmea_velocity_t velocity; 72 | char checksum; 73 | } nmea_gprmc_t; 74 | 75 | typedef struct _nmea_gpgga_t 76 | { 77 | nmea_time_t time; 78 | nmea_position_t position; 79 | uint8_t fix_quality; 80 | uint8_t satellites_tracked; 81 | float hdop; 82 | float altitude; 83 | float geoid_height; 84 | char checksum; 85 | } nmea_gpgga_t; 86 | 87 | typedef struct _nmea_gpgsa_t 88 | { 89 | char mode; 90 | char fix_type; 91 | uint8_t satellite_prn[12]; 92 | float pdop; 93 | float hdop; 94 | float vdop; 95 | char checksum; 96 | } nmea_gpgsa_t; 97 | 98 | typedef struct _nmea_gpgsv_satellite_t 99 | { 100 | uint8_t index; 101 | uint8_t prn; 102 | uint8_t altitude; 103 | uint16_t azimuth; 104 | uint8_t snr; 105 | } nmea_gpgsv_satellite_t; 106 | 107 | typedef struct _nmea_gpgsv_t 108 | { 109 | uint8_t sentence_total; 110 | uint8_t sentence_number; 111 | uint8_t satellites_in_view; 112 | nmea_gpgsv_satellite_t satellite[4]; 113 | char checksum; 114 | } nmea_gpgsv_t; 115 | 116 | extern unsigned int nmea_parse_gprmc(char *sentence, nmea_gprmc_t *data); 117 | extern unsigned int nmea_parse_gpgga(char *sentence, nmea_gpgga_t *data); 118 | extern unsigned int nmea_parse_gpgsa(char *sentence, nmea_gpgsa_t *data); 119 | extern unsigned int nmea_parse_gpgsv(char *sentence, nmea_gpgsv_t *data); 120 | 121 | #endif /* NMEA_H_ */ 122 | -------------------------------------------------------------------------------- /rtc/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | rtc 4 | 5 | 6 | i2c 7 | 8 | 9 | 10 | org.eclipse.cdt.managedbuilder.core.genmakebuilder 11 | clean,full,incremental, 12 | 13 | 14 | ?name? 15 | 16 | 17 | 18 | org.eclipse.cdt.make.core.append_environment 19 | true 20 | 21 | 22 | org.eclipse.cdt.make.core.autoBuildTarget 23 | all 24 | 25 | 26 | org.eclipse.cdt.make.core.buildArguments 27 | 28 | 29 | 30 | org.eclipse.cdt.make.core.buildCommand 31 | make 32 | 33 | 34 | org.eclipse.cdt.make.core.buildLocation 35 | ${workspace_loc:/rtc_ds1307/Release} 36 | 37 | 38 | org.eclipse.cdt.make.core.cleanBuildTarget 39 | clean 40 | 41 | 42 | org.eclipse.cdt.make.core.contents 43 | org.eclipse.cdt.make.core.activeConfigSettings 44 | 45 | 46 | org.eclipse.cdt.make.core.enableAutoBuild 47 | false 48 | 49 | 50 | org.eclipse.cdt.make.core.enableCleanBuild 51 | true 52 | 53 | 54 | org.eclipse.cdt.make.core.enableFullBuild 55 | true 56 | 57 | 58 | org.eclipse.cdt.make.core.fullBuildTarget 59 | all 60 | 61 | 62 | org.eclipse.cdt.make.core.stopOnError 63 | true 64 | 65 | 66 | org.eclipse.cdt.make.core.useDefaultBuildCmd 67 | true 68 | 69 | 70 | 71 | 72 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder 73 | 74 | 75 | 76 | 77 | 78 | org.eclipse.cdt.core.cnature 79 | org.eclipse.cdt.managedbuilder.core.managedBuildNature 80 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature 81 | de.innot.avreclipse.core.avrnature 82 | 83 | 84 | -------------------------------------------------------------------------------- /rtc/.settings/de.innot.avreclipse.core.prefs: -------------------------------------------------------------------------------- 1 | avrtarget/ClockFrequency=8000000 2 | avrtarget/ExtRAMSize=0 3 | avrtarget/ExtendedRAM=false 4 | avrtarget/MCUType=atmega644 5 | avrtarget/UseEEPROM=false 6 | avrtarget/UseExtendedRAMforHeap=true 7 | avrtarget/avrdude/BitBangDelay= 8 | avrtarget/avrdude/Bitclock=10 9 | avrtarget/avrdude/EEPROMFile= 10 | avrtarget/avrdude/EEPROMFromConfig=true 11 | avrtarget/avrdude/FlashFile= 12 | avrtarget/avrdude/FlashFromConfig=true 13 | avrtarget/avrdude/NoChipErase=false 14 | avrtarget/avrdude/NoSigCheck=false 15 | avrtarget/avrdude/NoVerify=false 16 | avrtarget/avrdude/NoWrite=false 17 | avrtarget/avrdude/OtherOptions= 18 | avrtarget/avrdude/ProgrammerID=programmerconfig.1 19 | avrtarget/avrdude/UseCounter=false 20 | avrtarget/avrdude/WriteEEPROM=false 21 | avrtarget/avrdude/WriteFlash=true 22 | avrtarget/de.innot.avreclipse.configuration.lib.release.1550075577.766250907.627179608/ClockFrequency=8000000 23 | avrtarget/de.innot.avreclipse.configuration.lib.release.1550075577.766250907.627179608/ExtRAMSize=0 24 | avrtarget/de.innot.avreclipse.configuration.lib.release.1550075577.766250907.627179608/ExtendedRAM=false 25 | avrtarget/de.innot.avreclipse.configuration.lib.release.1550075577.766250907.627179608/MCUType=atmega1284p 26 | avrtarget/de.innot.avreclipse.configuration.lib.release.1550075577.766250907.627179608/UseEEPROM=false 27 | avrtarget/de.innot.avreclipse.configuration.lib.release.1550075577.766250907.627179608/UseExtendedRAMforHeap=true 28 | avrtarget/de.innot.avreclipse.configuration.lib.release.1550075577.766250907/ClockFrequency=8000000 29 | avrtarget/de.innot.avreclipse.configuration.lib.release.1550075577.766250907/ExtRAMSize=0 30 | avrtarget/de.innot.avreclipse.configuration.lib.release.1550075577.766250907/ExtendedRAM=false 31 | avrtarget/de.innot.avreclipse.configuration.lib.release.1550075577.766250907/MCUType=atmega644 32 | avrtarget/de.innot.avreclipse.configuration.lib.release.1550075577.766250907/UseEEPROM=false 33 | avrtarget/de.innot.avreclipse.configuration.lib.release.1550075577.766250907/UseExtendedRAMforHeap=true 34 | avrtarget/perConfig=true 35 | eclipse.preferences.version=1 36 | -------------------------------------------------------------------------------- /rtc/rtc.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015, Jeremy Cole 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program 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. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | */ 19 | 20 | #include "rtc.h" 21 | 22 | uint8_t rtc_days_in_month[13][2] = { 23 | {0, 0}, 24 | {31, 31}, 25 | {28, 29}, 26 | {31, 31}, 27 | {30, 30}, 28 | {31, 31}, 29 | {30, 30}, 30 | {31, 31}, 31 | {31, 31}, 32 | {30, 30}, 33 | {31, 31}, 34 | {30, 30}, 35 | {31, 31} 36 | }; 37 | 38 | char *rtc_month_abbreviations[13] = { 39 | "", 40 | "Jan", 41 | "Feb", 42 | "Mar", 43 | "Apr", 44 | "May", 45 | "Jun", 46 | "Jul", 47 | "Aug", 48 | "Sep", 49 | "Oct", 50 | "Nov", 51 | "Dec" 52 | }; 53 | 54 | char *rtc_dow_names[8] = { 55 | "", 56 | "Sunday", 57 | "Monday", 58 | "Tuesday", 59 | "Wednesday", 60 | "Thursday", 61 | "Friday", 62 | "Saturday" 63 | }; 64 | 65 | uint8_t rtc_init(rtc_device_t *rtc) 66 | { 67 | return((*rtc->init)()); 68 | } 69 | 70 | uint8_t rtc_clock_start(rtc_device_t *rtc) 71 | { 72 | return((*rtc->clock_start)()); 73 | } 74 | 75 | uint8_t rtc_clock_stop(rtc_device_t *rtc) 76 | { 77 | return((*rtc->clock_stop)()); 78 | } 79 | 80 | uint8_t rtc_sqw_enable(rtc_device_t *rtc) 81 | { 82 | return((*rtc->sqw_enable)()); 83 | } 84 | 85 | uint8_t rtc_sqw_disable(rtc_device_t *rtc) 86 | { 87 | return((*rtc->sqw_disable)()); 88 | } 89 | 90 | uint8_t rtc_sqw_rate(rtc_device_t *rtc, uint16_t rate) 91 | { 92 | return((*rtc->sqw_rate)(rate)); 93 | } 94 | 95 | uint8_t rtc_read(rtc_device_t *rtc, rtc_datetime_24h_t *dt) 96 | { 97 | return((*rtc->read)(dt)); 98 | } 99 | 100 | uint8_t rtc_write(rtc_device_t *rtc, rtc_datetime_24h_t *dt) 101 | { 102 | return((*rtc->write)(dt)); 103 | } 104 | 105 | uint8_t rtc_find_dow(uint16_t y, uint8_t m, uint8_t d) 106 | { 107 | static uint8_t t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4}; 108 | y -= m < 3; 109 | return (uint8_t)(1 + ((y + y/4 - y/100 + y/400 + t[m-1] + d) % 7)); 110 | } 111 | 112 | int8_t rtc_find_dst_offset(rtc_datetime_24h_t time, rtc_dst_date_t dst_dates[]) 113 | { 114 | uint8_t i; 115 | 116 | for(i=0; dst_dates[i].year != 0; i++) 117 | { 118 | /* Skip through the dst_dates array looking for the current year. */ 119 | if(dst_dates[i].year > time.year) return(0); 120 | if(dst_dates[i].year < time.year) continue; 121 | 122 | /* The year matches, check the month, day, and hour to try to 123 | * discern whether DST is in effect. */ 124 | if( (time.month == dst_dates[i].start_month) && 125 | (time.date == dst_dates[i].start_date) && 126 | (time.hour >= 2) ) 127 | return(1); 128 | if( (time.month == dst_dates[i].end_month) && 129 | (time.date == dst_dates[i].end_date) && 130 | (time.hour < 2) ) 131 | return(1); 132 | if( (time.month == dst_dates[i].start_month) && 133 | (time.date > dst_dates[i].start_date) ) 134 | return(1); 135 | if( (time.month == dst_dates[i].end_month) && 136 | (time.date < dst_dates[i].end_date) ) 137 | return(1); 138 | if( (time.month > dst_dates[i].start_month) && 139 | (time.month < dst_dates[i].end_month) ) 140 | return(1); 141 | 142 | /* None of the above were true; DST is not in effect currently. */ 143 | return(0); 144 | } 145 | 146 | /* We didn't find an entry in the dst_dates list; assume no DST. */ 147 | return(0); 148 | } 149 | 150 | uint8_t rtc_offset_time(rtc_datetime_24h_t *from, rtc_datetime_24h_t *to, uint8_t offset_hours) 151 | { 152 | to->millisecond = from->millisecond; 153 | to->second = from->second; 154 | to->minute = from->minute; 155 | to->hour = from->hour; 156 | to->date = from->date; 157 | to->month = from->month; 158 | to->year = from->year; 159 | to->day_of_week = from->day_of_week; 160 | 161 | to->hour += offset_hours; 162 | 163 | if(to->hour < 0) 164 | { 165 | to->day_of_week -= 1; 166 | if(to->day_of_week == 0) 167 | { 168 | to->day_of_week = 7; 169 | } 170 | 171 | to->date -= 1; 172 | if(to->date == 0) 173 | { 174 | to->month -= 1; 175 | if(to->month == 0) 176 | { 177 | to->year -= 1; 178 | to->month = 12; 179 | } 180 | to->date = rtc_days_in_month[to->month][0]; /* XXX */ 181 | } 182 | to->hour += 24; 183 | } 184 | 185 | if(to->hour >= 24) 186 | { 187 | to->day_of_week += 1; 188 | if(to->day_of_week == 8) 189 | { 190 | to->day_of_week = 1; 191 | } 192 | 193 | to->date += 1; 194 | if(to->date > rtc_days_in_month[to->month][0]) 195 | { 196 | to->month += 1; 197 | if(to->month == 13) 198 | { 199 | to->year += 1; 200 | to->month = 1; 201 | } 202 | to->date = 1; 203 | } 204 | to->hour -= 24; 205 | } 206 | 207 | return 0; 208 | } 209 | 210 | -------------------------------------------------------------------------------- /rtc/rtc.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015, Jeremy Cole 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program 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. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | */ 19 | 20 | #ifndef RTC_H_ 21 | #define RTC_H_ 22 | 23 | #include 24 | #include "rtc_types.h" 25 | 26 | extern uint8_t rtc_days_in_month[13][2]; 27 | extern char *rtc_month_abbreviations[13]; 28 | extern char *rtc_dow_names[8]; 29 | 30 | extern uint8_t rtc_init(rtc_device_t *rtc); 31 | extern uint8_t rtc_clock_start(rtc_device_t *rtc); 32 | extern uint8_t rtc_clock_stop(rtc_device_t *rtc); 33 | extern uint8_t rtc_sqw_enable(rtc_device_t *rtc); 34 | extern uint8_t rtc_sqw_disable(rtc_device_t *rtc); 35 | extern uint8_t rtc_sqw_rate(rtc_device_t *rtc, uint16_t rate); 36 | extern uint8_t rtc_read(rtc_device_t *rtc, rtc_datetime_24h_t *dt); 37 | extern uint8_t rtc_write(rtc_device_t *rtc, rtc_datetime_24h_t *dt); 38 | 39 | extern uint8_t rtc_find_dow(uint16_t y, uint8_t m, uint8_t d); 40 | extern int8_t rtc_find_dst_offset(rtc_datetime_24h_t time, rtc_dst_date_t dst_dates[]); 41 | extern uint8_t rtc_offset_time(rtc_datetime_24h_t *from, rtc_datetime_24h_t *to, uint8_t offset_hours); 42 | 43 | #endif /* RTC_H_ */ 44 | -------------------------------------------------------------------------------- /rtc/rtc_ds1307.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015, Jeremy Cole 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program 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. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | */ 19 | 20 | #include 21 | #include "rtc_ds1307.h" 22 | 23 | uint8_t rtc_ds1307_hardware_init(void) 24 | { 25 | uint8_t rc; 26 | 27 | rc = i2c_start(RTC_DS1307_I2C_ID, I2C_WRITE); 28 | if(rc) return 1; 29 | 30 | rc = i2c_write(0x00); 31 | if(rc) return 2; 32 | 33 | i2c_stop(); 34 | 35 | rc = i2c_rep_start(RTC_DS1307_I2C_ID, I2C_READ); 36 | if(rc) return 3; 37 | 38 | i2c_read_nak(); 39 | i2c_stop(); 40 | 41 | return 0; 42 | } 43 | uint8_t rtc_ds1307_read_ram(uint8_t address, uint8_t length, unsigned char *data) 44 | { 45 | uint8_t rc; 46 | uint8_t pos; 47 | 48 | rc = i2c_start(RTC_DS1307_I2C_ID, I2C_WRITE); 49 | if(rc) return 1; 50 | 51 | rc = i2c_write(address); 52 | if(rc) return 2; 53 | 54 | i2c_stop(); 55 | 56 | rc = i2c_rep_start(RTC_DS1307_I2C_ID, I2C_READ); 57 | if(rc) return 3; 58 | 59 | for(pos=0; pos < length; pos++, data++) 60 | { 61 | *data = (char)i2c_read(pos != (length-1)); 62 | } 63 | i2c_stop(); 64 | 65 | return 0; 66 | } 67 | 68 | uint8_t rtc_ds1307_write_ram(uint8_t address, uint8_t length, unsigned char *data) 69 | { 70 | uint8_t rc; 71 | uint8_t pos; 72 | 73 | rc = i2c_start(RTC_DS1307_I2C_ID, I2C_WRITE); 74 | if(rc) return 1; 75 | 76 | rc = i2c_write(address); 77 | if(rc) return 2; 78 | 79 | for(pos=0; pos < length; pos++, data++) 80 | { 81 | rc = i2c_write((uint8_t)*data); 82 | if(rc) 83 | { 84 | i2c_stop(); 85 | return 3; 86 | } 87 | } 88 | 89 | i2c_stop(); 90 | 91 | return 0; 92 | } 93 | 94 | uint8_t rtc_ds1307_read_register(uint8_t address, uint8_t *value) 95 | { 96 | return rtc_ds1307_read_ram(address, 1, (uint8_t *)value); 97 | } 98 | 99 | uint8_t rtc_ds1307_write_register(uint8_t address, uint8_t *value) 100 | { 101 | return rtc_ds1307_write_ram(address, 1, (uint8_t *)value); 102 | } 103 | 104 | uint8_t rtc_ds1307_read_clock_raw(rtc_ds1307_clock_raw_t *raw) 105 | { 106 | return rtc_ds1307_read_ram(0x00, 8, (unsigned char *)raw); 107 | } 108 | 109 | uint8_t rtc_ds1307_write_clock_raw(rtc_ds1307_clock_raw_t *raw) 110 | { 111 | return rtc_ds1307_write_ram(0x00, 8, (unsigned char *)raw); 112 | } 113 | 114 | uint8_t rtc_ds1307_set_register_bit(uint8_t address, uint8_t bit, uint8_t value) 115 | { 116 | uint8_t rc; 117 | uint8_t data; 118 | 119 | rc = rtc_ds1307_read_register(address, &data); 120 | if(rc) return 1; 121 | 122 | if(value) 123 | { 124 | if(data & _BV(bit)) return 0; 125 | data |= _BV(bit); 126 | } 127 | else 128 | { 129 | if(!(data & _BV(bit))) return 0; 130 | data &= ~_BV(bit); 131 | } 132 | 133 | rc = rtc_ds1307_write_register(address, &data); 134 | if(rc) return 2; 135 | 136 | return 0; 137 | } 138 | 139 | uint8_t rtc_ds1307_hour_style(uint8_t style) 140 | { 141 | return rtc_ds1307_set_register_bit(RTC_DS1307_REGISTER_HOUR_STYLE, 142 | RTC_DS1307_CONTROL_HOUR_STYLE, style); 143 | } 144 | 145 | uint8_t rtc_ds1307_sqw_output_fixed(uint8_t output) 146 | { 147 | return rtc_ds1307_set_register_bit(RTC_DS1307_REGISTER_SQW_OUTPUT_FIXED, 148 | RTC_DS1307_CONTROL_SQW_OUTPUT_FIXED, output); 149 | } 150 | 151 | uint8_t rtc_ds1307_init(void) 152 | { 153 | uint8_t rc; 154 | 155 | rc = rtc_ds1307_hardware_init(); 156 | if(rc) return 1; 157 | 158 | rc = rtc_ds1307_hour_style(RTC_DS1307_HOUR_STYLE_24H); 159 | if(rc) return 2; 160 | 161 | return 0; 162 | } 163 | 164 | uint8_t rtc_ds1307_clock_start(void) 165 | { 166 | return rtc_ds1307_set_register_bit(RTC_DS1307_REGISTER_CLOCK_HALT, 167 | RTC_DS1307_CONTROL_CLOCK_HALT, RTC_DS1307_CLOCK_RUN); 168 | } 169 | 170 | uint8_t rtc_ds1307_clock_stop(void) 171 | { 172 | return rtc_ds1307_set_register_bit(RTC_DS1307_REGISTER_CLOCK_HALT, 173 | RTC_DS1307_CONTROL_CLOCK_HALT, RTC_DS1307_CLOCK_HALT); 174 | } 175 | 176 | uint8_t rtc_ds1307_sqw_enable(void) 177 | { 178 | return rtc_ds1307_set_register_bit(RTC_DS1307_REGISTER_SQW_ENABLE, 179 | RTC_DS1307_CONTROL_SQW_ENABLE, RTC_DS1307_SQW_ENABLE); 180 | } 181 | 182 | uint8_t rtc_ds1307_sqw_disable(void) 183 | { 184 | return rtc_ds1307_set_register_bit(RTC_DS1307_REGISTER_SQW_ENABLE, 185 | RTC_DS1307_CONTROL_SQW_ENABLE, RTC_DS1307_SQW_DISABLE); 186 | } 187 | 188 | uint8_t rtc_ds1307_sqw_rate(uint16_t rate) 189 | { 190 | uint8_t rc; 191 | uint8_t data; 192 | uint8_t rate_control_code; 193 | 194 | switch(rate) 195 | { 196 | case 1: 197 | rate_control_code = RTC_DS1307_SQW_RATE_1HZ; 198 | break; 199 | case 4096: 200 | rate_control_code = RTC_DS1307_SQW_RATE_4096HZ; 201 | break; 202 | case 8192: 203 | rate_control_code = RTC_DS1307_SQW_RATE_8192HZ; 204 | break; 205 | case 32768: 206 | rate_control_code = RTC_DS1307_SQW_RATE_32768HZ; 207 | break; 208 | default: 209 | return 1; 210 | } 211 | 212 | rc = rtc_ds1307_read_register(RTC_DS1307_REGISTER_SQW_RATE, &data); 213 | if(rc) return 1; 214 | 215 | data &= ~(3 << RTC_DS1307_CONTROL_SQW_RATE); 216 | data |= (rate_control_code & 3) << RTC_DS1307_CONTROL_SQW_RATE; 217 | 218 | rc = rtc_ds1307_write_register(RTC_DS1307_REGISTER_SQW_RATE, &data); 219 | if(rc) return 2; 220 | 221 | return 0; 222 | } 223 | 224 | uint8_t rtc_ds1307_read(rtc_datetime_24h_t *dt) 225 | { 226 | uint8_t rc; 227 | rtc_ds1307_clock_raw_t raw; 228 | 229 | rc = rtc_ds1307_read_clock_raw(&raw); 230 | if(rc) return rc; 231 | 232 | if(raw.control_mode_24h == RTC_DS1307_HOUR_STYLE_12H) 233 | return 100; 234 | 235 | dt->year = (raw.year_1 * 10) + raw.year_0; 236 | dt->month = (raw.month_1 * 10) + raw.month_0; 237 | dt->date = (raw.date_1 * 10) + raw.date_0; 238 | dt->hour = (raw.hour_1 * 10) + raw.hour_0; 239 | dt->minute = (raw.minute_1 * 10) + raw.minute_0; 240 | dt->second = (raw.second_1 * 10) + raw.second_0; 241 | dt->millisecond = 0; /* Not supported by this RTC */ 242 | dt->day_of_week = raw.day_of_week; 243 | 244 | dt->year += (dt->year < RTC_DS1307_YEAR_EPOCH)?2000:1900; 245 | 246 | return 0; 247 | } 248 | 249 | uint8_t rtc_ds1307_write(rtc_datetime_24h_t *dt) 250 | { 251 | uint8_t rc; 252 | rtc_ds1307_clock_raw_t raw; 253 | uint16_t tmp_year; 254 | 255 | rc = rtc_ds1307_read_clock_raw(&raw); 256 | if(rc) return rc; 257 | 258 | if(raw.control_mode_24h == RTC_DS1307_HOUR_STYLE_12H) 259 | return 100; 260 | 261 | tmp_year = dt->year - ((dt->year>=2000)?2000:1900); 262 | raw.year_0 = tmp_year % 10; 263 | raw.year_1 = (tmp_year - raw.year_0) / 10; 264 | 265 | raw.month_0 = dt->month % 10; 266 | raw.month_1 = (dt->month - raw.month_0) / 10; 267 | 268 | raw.date_0 = dt->date % 10; 269 | raw.date_1 = (dt->date - raw.date_0) / 10; 270 | 271 | raw.hour_0 = dt->hour % 10; 272 | raw.hour_1 = (dt->hour - raw.hour_0) / 10; 273 | 274 | raw.minute_0 = dt->minute % 10; 275 | raw.minute_1 = (dt->minute - raw.minute_0) / 10; 276 | 277 | raw.second_0 = dt->second % 10; 278 | raw.second_1 = (dt->second - raw.second_0) / 10; 279 | 280 | raw.day_of_week = dt->day_of_week; 281 | 282 | rc = rtc_ds1307_write_clock_raw(&raw); 283 | if(rc) return rc; 284 | 285 | return 0; 286 | } 287 | 288 | rtc_device_t rtc_ds1307 = { 289 | .init = rtc_ds1307_init, 290 | .clock_start = rtc_ds1307_clock_start, 291 | .clock_stop = rtc_ds1307_clock_stop, 292 | .sqw_enable = rtc_ds1307_sqw_enable, 293 | .sqw_disable = rtc_ds1307_sqw_disable, 294 | .sqw_rate = rtc_ds1307_sqw_rate, 295 | .read = rtc_ds1307_read, 296 | .write = rtc_ds1307_write 297 | }; 298 | -------------------------------------------------------------------------------- /rtc/rtc_ds1307.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015, Jeremy Cole 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program 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. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | */ 19 | 20 | #ifndef RTC_DS1307_H 21 | #define RTC_DS1307_H 22 | 23 | #include 24 | #include 25 | 26 | #include "rtc_types.h" 27 | 28 | #define RTC_DS1307_I2C_ID 0xD0 29 | 30 | #define RTC_DS1307_YEAR_EPOCH 50 31 | 32 | #define RTC_DS1307_CLOCK_HALT 1 33 | #define RTC_DS1307_CLOCK_RUN 0 34 | 35 | #define RTC_DS1307_HOUR_STYLE_24H 0 36 | #define RTC_DS1307_HOUR_STYLE_12H 1 37 | 38 | #define RTC_DS1307_SQW_DISABLE 0 39 | #define RTC_DS1307_SQW_ENABLE 1 40 | 41 | #define RTC_DS1307_SQW_RS1 1 42 | #define RTC_DS1307_SQW_RS0 0 43 | 44 | #define RTC_DS1307_SQW_RATE_1HZ ( 0 ) 45 | #define RTC_DS1307_SQW_RATE_4096HZ ( _BV(RTC_DS1307_SQW_RS0) ) 46 | #define RTC_DS1307_SQW_RATE_8192HZ ( _BV(RTC_DS1307_SQW_RS1) ) 47 | #define RTC_DS1307_SQW_RATE_32768HZ ( _BV(RTC_DS1307_SQW_RS1) | _BV(RTC_DS1307_SQW_RS0) ) 48 | 49 | #define RTC_DS1307_CONTROL_CLOCK_HALT 7 50 | #define RTC_DS1307_CONTROL_HOUR_STYLE 6 51 | #define RTC_DS1307_CONTROL_SQW_RATE 0 52 | #define RTC_DS1307_CONTROL_SQW_OUTPUT_FIXED 7 53 | #define RTC_DS1307_CONTROL_SQW_ENABLE 4 54 | 55 | #define RTC_DS1307_REGISTER_CLOCK_HALT 0x00 56 | #define RTC_DS1307_REGISTER_HOUR_STYLE 0x02 57 | #define RTC_DS1307_REGISTER_SQW_RATE 0x07 58 | #define RTC_DS1307_REGISTER_SQW_OUTPUT_FIXED 0x07 59 | #define RTC_DS1307_REGISTER_SQW_ENABLE 0x07 60 | 61 | typedef struct _rtc_ds1307_clock_raw_t 62 | { 63 | uint8_t second_0:4; 64 | uint8_t second_1:3; 65 | uint8_t control_clock_halt:1; 66 | uint8_t minute_0:4; 67 | uint8_t minute_1:3; 68 | uint8_t padding0:1; 69 | uint8_t hour_0:4; 70 | uint8_t hour_1:2; 71 | uint8_t control_mode_24h:1; 72 | uint8_t padding1:1; 73 | uint8_t day_of_week:3; 74 | uint8_t padding2:5; 75 | uint8_t date_0:4; 76 | uint8_t date_1:2; 77 | uint8_t padding3:2; 78 | uint8_t month_0:4; 79 | uint8_t month_1:1; 80 | uint8_t padding4:3; 81 | uint8_t year_0:4; 82 | uint8_t year_1:4; 83 | uint8_t control_rs:2; 84 | uint8_t padding5:2; 85 | uint8_t control_sqwe:1; 86 | uint8_t padding6:2; 87 | uint8_t control_out:1; 88 | } rtc_ds1307_clock_raw_t; 89 | 90 | extern rtc_device_t rtc_ds1307; 91 | 92 | #endif /* RTC_DS1307_H */ 93 | -------------------------------------------------------------------------------- /rtc/rtc_types.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015, Jeremy Cole 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program 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. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | */ 19 | 20 | #ifndef RTC_TYPES_H_ 21 | #define RTC_TYPES_H_ 22 | 23 | #include 24 | 25 | typedef struct _rtc_datetime_24h_t 26 | { 27 | int16_t year; 28 | int8_t month; 29 | int8_t date; 30 | int8_t hour; 31 | int8_t minute; 32 | int8_t second; 33 | int16_t millisecond; 34 | int8_t day_of_week; 35 | } rtc_datetime_24h_t; 36 | 37 | typedef struct _rtc_device_t 38 | { 39 | uint8_t (*init)(void); 40 | uint8_t (*clock_start)(void); 41 | uint8_t (*clock_stop)(void); 42 | uint8_t (*sqw_enable)(void); 43 | uint8_t (*sqw_disable)(void); 44 | uint8_t (*sqw_rate)(uint16_t); 45 | uint8_t (*read)(rtc_datetime_24h_t *); 46 | uint8_t (*write)(rtc_datetime_24h_t *); 47 | } rtc_device_t; 48 | 49 | typedef struct _rtc_dst_date_t 50 | { 51 | int16_t year; 52 | int8_t start_month; 53 | int8_t start_date; 54 | int8_t end_month; 55 | int8_t end_date; 56 | } rtc_dst_date_t; 57 | 58 | #endif /* RTC_TYPES_H_ */ 59 | -------------------------------------------------------------------------------- /rtc_test/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | rtc_test 4 | 5 | 6 | i2c 7 | rtc 8 | uart 9 | 10 | 11 | 12 | org.eclipse.cdt.managedbuilder.core.genmakebuilder 13 | clean,full,incremental, 14 | 15 | 16 | ?name? 17 | 18 | 19 | 20 | org.eclipse.cdt.make.core.append_environment 21 | true 22 | 23 | 24 | org.eclipse.cdt.make.core.autoBuildTarget 25 | all 26 | 27 | 28 | org.eclipse.cdt.make.core.buildArguments 29 | 30 | 31 | 32 | org.eclipse.cdt.make.core.buildCommand 33 | make 34 | 35 | 36 | org.eclipse.cdt.make.core.buildLocation 37 | ${workspace_loc:/rtc_i2c/Release} 38 | 39 | 40 | org.eclipse.cdt.make.core.cleanBuildTarget 41 | clean 42 | 43 | 44 | org.eclipse.cdt.make.core.contents 45 | org.eclipse.cdt.make.core.activeConfigSettings 46 | 47 | 48 | org.eclipse.cdt.make.core.enableAutoBuild 49 | false 50 | 51 | 52 | org.eclipse.cdt.make.core.enableCleanBuild 53 | true 54 | 55 | 56 | org.eclipse.cdt.make.core.enableFullBuild 57 | true 58 | 59 | 60 | org.eclipse.cdt.make.core.fullBuildTarget 61 | all 62 | 63 | 64 | org.eclipse.cdt.make.core.stopOnError 65 | true 66 | 67 | 68 | org.eclipse.cdt.make.core.useDefaultBuildCmd 69 | true 70 | 71 | 72 | 73 | 74 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder 75 | 76 | 77 | 78 | 79 | 80 | org.eclipse.cdt.core.cnature 81 | org.eclipse.cdt.managedbuilder.core.managedBuildNature 82 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature 83 | de.innot.avreclipse.core.avrnature 84 | 85 | 86 | -------------------------------------------------------------------------------- /rtc_test/.settings/de.innot.avreclipse.core.prefs: -------------------------------------------------------------------------------- 1 | #Tue Aug 17 18:17:58 PDT 2010 2 | avrtarget/ClockFrequency=8000000 3 | avrtarget/ExtRAMSize=0 4 | avrtarget/ExtendedRAM=false 5 | avrtarget/MCUType=atmega644 6 | avrtarget/UseEEPROM=false 7 | avrtarget/UseExtendedRAMforHeap=true 8 | avrtarget/avrdude/BitBangDelay= 9 | avrtarget/avrdude/Bitclock=10 10 | avrtarget/avrdude/EEPROMFile= 11 | avrtarget/avrdude/EEPROMFromConfig=true 12 | avrtarget/avrdude/FlashFile= 13 | avrtarget/avrdude/FlashFromConfig=true 14 | avrtarget/avrdude/Fuses/ByteValues=194\:25\:255 15 | avrtarget/avrdude/Fuses/FileName= 16 | avrtarget/avrdude/Fuses/MCUid=atmega644p 17 | avrtarget/avrdude/Fuses/UseFile=false 18 | avrtarget/avrdude/Fuses/Write=true 19 | avrtarget/avrdude/Locks/ByteValues=-1 20 | avrtarget/avrdude/Locks/FileName= 21 | avrtarget/avrdude/Locks/MCUid=atmega644p 22 | avrtarget/avrdude/Locks/UseFile=false 23 | avrtarget/avrdude/Locks/Write=false 24 | avrtarget/avrdude/NoChipErase=false 25 | avrtarget/avrdude/NoSigCheck=false 26 | avrtarget/avrdude/NoVerify=false 27 | avrtarget/avrdude/NoWrite=false 28 | avrtarget/avrdude/OtherOptions= 29 | avrtarget/avrdude/ProgrammerID=programmerconfig.1 30 | avrtarget/avrdude/UseCounter=false 31 | avrtarget/avrdude/WriteEEPROM=false 32 | avrtarget/avrdude/WriteFlash=true 33 | avrtarget/perConfig=false 34 | eclipse.preferences.version=1 35 | -------------------------------------------------------------------------------- /rtc_test/rtc_test.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Jeremy Cole 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program 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. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | int main(void) 35 | { 36 | uart_t *u0; 37 | uint8_t rc; 38 | rtc_device_t *rtc = &rtc_ds1307; 39 | rtc_datetime_24h_t current_dt, offset_dt; 40 | 41 | _delay_ms(1000); 42 | 43 | u0 = uart_init("0", UART_BAUD_SELECT(38400, F_CPU)); 44 | uart_init_stdout(u0); 45 | 46 | i2c_init(); 47 | 48 | DDRC = _BV(PC0) | _BV(PC1); 49 | PORTC = _BV(PC0) | _BV(PC1); 50 | 51 | sei(); 52 | 53 | printf("\n\nBooted up!\n"); 54 | 55 | rc = rtc_init(rtc); 56 | printf("Inited RTC, rc=%i\n", rc); 57 | 58 | rc = rtc_sqw_rate(rtc, 1); 59 | printf("Set sqw rate, rc=%i\n", rc); 60 | 61 | rc = rtc_sqw_enable(rtc); 62 | printf("Set sqw enable, rc=%i\n", rc); 63 | 64 | rc = rtc_clock_start(rtc); 65 | printf("Started clock, rc=%i\n", rc); 66 | 67 | _delay_ms(1000); 68 | 69 | while(1) 70 | { 71 | rc = rtc_read(rtc, ¤t_dt); 72 | 73 | rtc_offset_time(¤t_dt, &offset_dt, -7); 74 | 75 | printf("rc = %i, %04i-%02i-%02i %02i:%02i:%02i %i offset: %04i-%02i-%02i %02i:%02i:%02i %i\n", 76 | rc, 77 | current_dt.year, current_dt.month, current_dt.date, 78 | current_dt.hour, current_dt.minute, current_dt.second, 79 | current_dt.day_of_week, 80 | offset_dt.year, offset_dt.month, offset_dt.date, 81 | offset_dt.hour, offset_dt.minute, offset_dt.second, 82 | offset_dt.day_of_week 83 | ); 84 | 85 | _delay_ms(1000); 86 | } 87 | 88 | return(0); 89 | } 90 | -------------------------------------------------------------------------------- /uart/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | uart 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.cdt.managedbuilder.core.genmakebuilder 10 | clean,full,incremental, 11 | 12 | 13 | ?name? 14 | 15 | 16 | 17 | org.eclipse.cdt.make.core.append_environment 18 | true 19 | 20 | 21 | org.eclipse.cdt.make.core.autoBuildTarget 22 | all 23 | 24 | 25 | org.eclipse.cdt.make.core.buildArguments 26 | 27 | 28 | 29 | org.eclipse.cdt.make.core.buildCommand 30 | make 31 | 32 | 33 | org.eclipse.cdt.make.core.buildLocation 34 | ${workspace_loc:/uart/Release} 35 | 36 | 37 | org.eclipse.cdt.make.core.cleanBuildTarget 38 | clean 39 | 40 | 41 | org.eclipse.cdt.make.core.contents 42 | org.eclipse.cdt.make.core.activeConfigSettings 43 | 44 | 45 | org.eclipse.cdt.make.core.enableAutoBuild 46 | false 47 | 48 | 49 | org.eclipse.cdt.make.core.enableCleanBuild 50 | true 51 | 52 | 53 | org.eclipse.cdt.make.core.enableFullBuild 54 | true 55 | 56 | 57 | org.eclipse.cdt.make.core.fullBuildTarget 58 | all 59 | 60 | 61 | org.eclipse.cdt.make.core.stopOnError 62 | true 63 | 64 | 65 | org.eclipse.cdt.make.core.useDefaultBuildCmd 66 | true 67 | 68 | 69 | 70 | 71 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder 72 | 73 | 74 | 75 | 76 | 77 | org.eclipse.cdt.core.cnature 78 | org.eclipse.cdt.managedbuilder.core.managedBuildNature 79 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature 80 | de.innot.avreclipse.core.avrnature 81 | 82 | 83 | -------------------------------------------------------------------------------- /uart/.settings/de.innot.avreclipse.core.prefs: -------------------------------------------------------------------------------- 1 | avrtarget/ClockFrequency=8000000 2 | avrtarget/ExtRAMSize=0 3 | avrtarget/ExtendedRAM=false 4 | avrtarget/MCUType=atmega644 5 | avrtarget/UseEEPROM=false 6 | avrtarget/UseExtendedRAMforHeap=true 7 | avrtarget/de.innot.avreclipse.configuration.lib.release.1460611472.2131147354.1163634307/ClockFrequency=8000000 8 | avrtarget/de.innot.avreclipse.configuration.lib.release.1460611472.2131147354.1163634307/ExtRAMSize=0 9 | avrtarget/de.innot.avreclipse.configuration.lib.release.1460611472.2131147354.1163634307/ExtendedRAM=false 10 | avrtarget/de.innot.avreclipse.configuration.lib.release.1460611472.2131147354.1163634307/MCUType=atmega1284p 11 | avrtarget/de.innot.avreclipse.configuration.lib.release.1460611472.2131147354.1163634307/UseEEPROM=false 12 | avrtarget/de.innot.avreclipse.configuration.lib.release.1460611472.2131147354.1163634307/UseExtendedRAMforHeap=true 13 | avrtarget/de.innot.avreclipse.configuration.lib.release.1460611472.2131147354/ClockFrequency=8000000 14 | avrtarget/de.innot.avreclipse.configuration.lib.release.1460611472.2131147354/ExtRAMSize=0 15 | avrtarget/de.innot.avreclipse.configuration.lib.release.1460611472.2131147354/ExtendedRAM=false 16 | avrtarget/de.innot.avreclipse.configuration.lib.release.1460611472.2131147354/MCUType=atmega644 17 | avrtarget/de.innot.avreclipse.configuration.lib.release.1460611472.2131147354/UseEEPROM=false 18 | avrtarget/de.innot.avreclipse.configuration.lib.release.1460611472.2131147354/UseExtendedRAMforHeap=true 19 | avrtarget/perConfig=true 20 | eclipse.preferences.version=1 21 | -------------------------------------------------------------------------------- /uart/README: -------------------------------------------------------------------------------- 1 | Interrupt-driven UART library with support for multiple UARTs, using ring 2 | buffers for receive/transmit and support for stdout/printf. At compile time, 3 | all UARTs are detected and populated into the uart_descriptions global 4 | structure, which is used by other functions during runtime. 5 | 6 | The core of this library is closely based on Peter Fleury's UART library, 7 | with heavy refactoring, reformatting, and updating. 8 | 9 | This library is based on Peter Fleury's original files with the IDs: 10 | "uart.c,v 1.6.2.1 2007/07/01 11:14:38" 11 | "uart.h,v 1.8.2.1 2007/07/01 11:14:38" 12 | 13 | Peter's copyright is as follows: 14 | Copyright (c) 2006 Peter Fleury http://jump.to/fleury 15 | 16 | DESCRIPTION: 17 | An interrupt is generated when the UART has finished transmitting or 18 | receiving a byte. The interrupt handling routines use circular buffers 19 | for buffering received and transmitted data. 20 | 21 | The UART_RX_BUFFER_SIZE and UART_TX_BUFFER_SIZE variables define 22 | the buffer size in bytes. Note that these variables must be a 23 | power of 2. 24 | 25 | USAGE: 26 | Refer to the header file uart.h for a description of the routines. 27 | See also example test_uart.c. 28 | 29 | NOTES: 30 | Originally based on Atmel Application Note AVR306. 31 | -------------------------------------------------------------------------------- /uart/TODO: -------------------------------------------------------------------------------- 1 | Current TODO list is: 2 | 3 | * Ability to shut down a UART after having used it, freeing the buffers 4 | allocated and shutting it down. 5 | 6 | * Ability to temporarily suspend a UART to save power? 7 | 8 | * Ability to toggle an RTS pin for RS485 half-duplex. 9 | 10 | * Test more ATmega MCUs, especially with 2+ UARTs. 11 | 12 | * Optimization of the ISRs to not do string based searches for every call. 13 | 14 | * Add support for the ATxmega MCUs, especially with 4+ UARTs. -------------------------------------------------------------------------------- /uart/uart.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Jeremy Cole 3 | Copyright (c) 2006, Peter Fleury 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | */ 20 | 21 | #include "uart.h" 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | /* 31 | * Module global variables 32 | */ 33 | 34 | uart_instance_t *uart_instances = NULL; 35 | uart_stdout_t uart_stdout; 36 | 37 | #include "uart_quirks.h" 38 | 39 | #if defined(UART0_RXC_INT) && defined(UART0_DRE_INT) 40 | ISR(UART0_RXC_INT) { uart_isr_rxc("0"); } 41 | ISR(UART0_DRE_INT) { uart_isr_dre("0"); } 42 | #endif 43 | 44 | #if defined(USART1_RX_vect) 45 | ISR(USART1_RX_vect) { uart_isr_rxc("1"); } 46 | ISR(USART1_UDRE_vect) { uart_isr_dre("1"); } 47 | #endif 48 | 49 | #if defined(USART2_RX_vect) 50 | ISR(USART2_RX_vect) { uart_isr_rxc("2"); } 51 | ISR(USART2_UDRE_vect) { uart_isr_dre("2"); } 52 | #endif 53 | 54 | #if defined(USART3_RX_vect) 55 | ISR(USART3_RX_vect) { uart_isr_rxc("3"); } 56 | ISR(USART3_UDRE_vect) { uart_isr_dre("3"); } 57 | #endif 58 | 59 | 60 | inline uart_instance_t *uart_instance_add(uart_t *uart) 61 | { 62 | uart_instance_t *instance, *current; 63 | 64 | instance = malloc(sizeof(uart_instance_t)); 65 | 66 | if(uart_instances == NULL) 67 | { 68 | uart_instances = instance; 69 | } else { 70 | for(current = uart_instances; current->next; current = current->next) { }; 71 | current->next = instance; 72 | } 73 | instance->next = NULL; 74 | instance->uart = uart; 75 | 76 | return uart_instances; 77 | } 78 | 79 | uart_t *uart_by_name(char *name) 80 | { 81 | uart_instance_t *instance; 82 | for(instance=uart_instances; instance; instance = instance->next) 83 | { 84 | if(!(strcmp(instance->uart->description->name, name))) 85 | return instance->uart; 86 | } 87 | return NULL; 88 | } 89 | 90 | uart_description_t *uart_description_by_name(char *name) 91 | { 92 | uart_description_t *d; 93 | for(d=uart_descriptions; d; d++) 94 | { 95 | if(!(strcmp(d->name, name))) 96 | return d; 97 | } 98 | return NULL; 99 | } 100 | 101 | uart_t *uart_init(char *name, unsigned int baudrate) 102 | { 103 | uart_t *uart; 104 | uart_description_t *description; 105 | 106 | description = uart_description_by_name(name); 107 | 108 | uart = malloc(sizeof(uart_t)); 109 | uart->tx.buffer = malloc(UART_TX_BUFFER_SIZE); 110 | uart->rx.buffer = malloc(UART_RX_BUFFER_SIZE); 111 | uart->tx.head = 0; 112 | uart->tx.tail = 0; 113 | uart->rx.head = 0; 114 | uart->rx.tail = 0; 115 | uart->rx_callback = NULL; 116 | uart->description = description; 117 | 118 | uart_set_baudrate(uart, baudrate); 119 | 120 | /* Set frame format: asynchronous, 8data, no parity, 1stop bit */ 121 | uart_set_frame_format(uart, 122 | uart->description->format_async 123 | | uart->description->format_8n1); 124 | 125 | /* Enable UART receiver, transmitter, and RX complete interrupt. */ 126 | if(uart->description->control_enable) 127 | { 128 | *uart->description->registers.control |= uart->description->control_enable; 129 | } 130 | 131 | uart_instance_add(uart); 132 | 133 | return uart; 134 | } 135 | 136 | void uart_set_baudrate(uart_t *uart, unsigned int baudrate) 137 | { 138 | if( uart->description->status_u2x && (baudrate & UART_BAUD_RATE_2X) ) 139 | { 140 | /* Enable 2x speed */ 141 | *uart->description->registers.status = uart->description->status_u2x; 142 | } 143 | 144 | baudrate &= ~UART_BAUD_RATE_2X; 145 | 146 | /* Set baud rate */ 147 | if(uart->description->registers.baud_h) 148 | { 149 | *uart->description->registers.baud_h = (unsigned char) (baudrate >> 8); 150 | } 151 | 152 | *uart->description->registers.baud_l = (unsigned char) (baudrate & 0x00ff); 153 | } 154 | 155 | void uart_set_frame_format(uart_t *uart, int frame_format) 156 | { 157 | /* TODO: Make this resettable by not just using |= */ 158 | *uart->description->registers.format |= frame_format; 159 | } 160 | 161 | void uart_set_rx_callback(uart_t *uart, void (*rx_callback)(uart_t *)) 162 | { 163 | uart->rx_callback = rx_callback; 164 | } 165 | 166 | void uart_isr_rxc(char *name) 167 | { 168 | uart_t *uart; 169 | unsigned char tmp_rx_head; 170 | unsigned char data; 171 | unsigned char usr; 172 | unsigned char rx_error; 173 | 174 | uart = uart_by_name(name); 175 | 176 | /* Read UART status register and UART data register */ 177 | usr = *uart->description->registers.status; 178 | data = *uart->description->registers.data; 179 | 180 | rx_error = (usr & (uart->description->error_fe | uart->description->error_dor) ); 181 | 182 | /* calculate buffer index */ 183 | tmp_rx_head = ( uart->rx.head + 1) & UART_RX_BUFFER_MASK; 184 | 185 | if ( tmp_rx_head == uart->rx.tail ) 186 | { 187 | /* error: receive buffer overflow */ 188 | rx_error = UART_BUFFER_OVERFLOW >> 8; 189 | } else { 190 | /* store new index */ 191 | uart->rx.head = tmp_rx_head; 192 | /* store received data in buffer */ 193 | uart->rx.buffer[tmp_rx_head] = data; 194 | } 195 | uart->rx.error = rx_error; 196 | 197 | if(uart->rx_callback) 198 | uart->rx_callback(uart); 199 | } 200 | 201 | void uart_isr_dre(char *name) 202 | { 203 | uart_t *uart; 204 | unsigned char tmp_tx_tail; 205 | 206 | uart = uart_by_name(name); 207 | 208 | if ( uart->tx.head != uart->tx.tail) 209 | { 210 | /* Calculate and store new buffer index */ 211 | tmp_tx_tail = (uart->tx.tail + 1) & UART_TX_BUFFER_MASK; 212 | uart->tx.tail = tmp_tx_tail; 213 | /* Get one byte from buffer and write it to UART */ 214 | *uart->description->registers.data = uart->tx.buffer[tmp_tx_tail]; /* start transmission */ 215 | } else { 216 | /* TX buffer empty, disable UDRE interrupt */ 217 | *uart->description->registers.control &= ~uart->description->control_udrie; 218 | } 219 | } 220 | 221 | unsigned char uart_data_ready(uart_t *uart) 222 | { 223 | if (uart->rx.head == uart->rx.tail) 224 | return 0; 225 | return 1; 226 | } 227 | 228 | unsigned int uart_getc(uart_t *uart) 229 | { 230 | unsigned char tmp_rx_tail, data; 231 | 232 | if (uart_data_ready(uart) == 0) 233 | { 234 | return UART_NO_DATA; /* no data available */ 235 | } 236 | 237 | /* Calculate new tail of receive buffer */ 238 | tmp_rx_tail = (uart->rx.tail + 1) & UART_RX_BUFFER_MASK; 239 | 240 | /* Get data from new tail of receive buffer */ 241 | data = uart->rx.buffer[tmp_rx_tail]; 242 | 243 | /* Adjust tail pointer, allowing writes into buffer to unblock */ 244 | uart->rx.tail = tmp_rx_tail; 245 | 246 | return (uart->rx.error << 8) + data; 247 | } 248 | 249 | void uart_putc(uart_t *uart, unsigned char data) 250 | { 251 | unsigned char tmp_tx_head; 252 | 253 | tmp_tx_head = (uart->tx.head + 1) & UART_TX_BUFFER_MASK; 254 | 255 | while ( tmp_tx_head == uart->tx.tail ){ 256 | /* Wait for free space in buffer. */ 257 | } 258 | 259 | uart->tx.buffer[tmp_tx_head] = data; 260 | uart->tx.head = tmp_tx_head; 261 | 262 | /* enable UDRE interrupt */ 263 | *uart->description->registers.control |= uart->description->control_udrie; 264 | } 265 | 266 | void uart_puts(uart_t *uart, const char *s) 267 | { 268 | while (*s) 269 | uart_putc(uart, *s++); 270 | } 271 | 272 | void uart_puts_P(uart_t *uart, const char *progmem_s) 273 | { 274 | register char c; 275 | 276 | while ( (c = pgm_read_byte(progmem_s++)) ) 277 | uart_putc(uart, c); 278 | } 279 | 280 | void uart_init_stdout(uart_t *uart) 281 | { 282 | uart_stdout.uart = uart; 283 | fdev_setup_stream(&uart_stdout.file, uart_putchar, NULL, _FDEV_SETUP_WRITE); 284 | stdout = &uart_stdout.file; 285 | stderr = &uart_stdout.file; 286 | } 287 | 288 | int uart_putchar(char c, FILE *stream) 289 | { 290 | if(c == '\n') 291 | uart_putchar('\r', stream); 292 | 293 | uart_putc(uart_stdout.uart, c); 294 | 295 | return 0; 296 | } 297 | -------------------------------------------------------------------------------- /uart/uart.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Jeremy Cole 3 | Copyright (c) 2006, Peter Fleury 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | */ 20 | 21 | /** 22 | * @defgroup pfleury_uart UART Library 23 | * @code #include @endcode 24 | * 25 | * @brief Interrupt UART library using the built-in UART with transmit and receive circular buffers. 26 | * 27 | * This library can be used to transmit and receive data through the built in UART. 28 | * 29 | * An interrupt is generated when the UART has finished transmitting or 30 | * receiving a byte. The interrupt handling routines use circular buffers 31 | * for buffering received and transmitted data. 32 | * 33 | * @note Based on Atmel Application Note AVR306 34 | * @author Peter Fleury pfleury@gmx.ch http://jump.to/fleury 35 | */ 36 | 37 | /**@{*/ 38 | 39 | #ifndef UART_H 40 | #define UART_H 41 | 42 | #include 43 | #include 44 | #include 45 | #include 46 | 47 | #include "uart_description.h" 48 | 49 | #if (__GNUC__ * 100 + __GNUC_MINOR__) < 304 50 | #error "This library requires AVR-GCC 3.4 or later, update to newer AVR-GCC compiler !" 51 | #endif 52 | 53 | typedef struct _uart_buffer_t 54 | { 55 | volatile unsigned char *buffer; 56 | volatile unsigned char head; 57 | volatile unsigned char tail; 58 | volatile unsigned char error; 59 | } uart_buffer_t; 60 | 61 | 62 | typedef struct _uart_t 63 | { 64 | uart_description_t *description; 65 | uart_buffer_t tx; 66 | uart_buffer_t rx; 67 | void (*rx_callback)(struct _uart_t *); 68 | } uart_t; 69 | 70 | typedef struct _uart_stdout_t 71 | { 72 | uart_t *uart; 73 | FILE file; 74 | } uart_stdout_t; 75 | 76 | typedef struct _uart_instance_t 77 | { 78 | uart_t *uart; 79 | struct _uart_instance_t *next; 80 | } uart_instance_t; 81 | 82 | extern uart_instance_t *uart_instances; 83 | extern uart_stdout_t uart_stdout; 84 | 85 | extern uart_t *uart_by_name(char *name); 86 | extern uart_description_t *uart_description_by_name(char *name); 87 | 88 | extern void uart_init_stdout(uart_t *uart); 89 | extern int uart_putchar(char c, FILE *stream); 90 | 91 | extern uart_t *uart_init(char *name, unsigned int baudrate); 92 | extern void uart_set_baudrate(uart_t *uart, unsigned int baudrate); 93 | extern void uart_set_frame_format(uart_t *uart, int frame_format); 94 | extern void uart_set_rx_callback(uart_t *uart, void (*rx_callback)(uart_t *)); 95 | extern void uart_isr_rxc(char *name); 96 | extern void uart_isr_dre(char *name); 97 | extern unsigned char uart_data_ready(uart_t *uart); 98 | extern unsigned int uart_getc(uart_t *uart); 99 | extern void uart_putc(uart_t *uart, unsigned char data); 100 | extern void uart_puts(uart_t *uart, const char *s); 101 | extern void uart_puts_P(uart_t *uart, const char *progmem_s); 102 | 103 | /* 104 | ** constants and macros 105 | */ 106 | 107 | /** The high bit in the baud rate is used to indicate that double speed 108 | * should be used when initializing the UART. 109 | */ 110 | #define UART_BAUD_RATE_2X 0x8000 111 | 112 | /** @brief UART Baudrate Expression 113 | * @param xtalcpu system clock in Mhz, e.g. 4000000L for 4Mhz 114 | * @param baudrate baudrate in bps, e.g. 1200, 2400, 9600 115 | */ 116 | #define UART_BAUD_SELECT(baud_rate, xtal_cpu) \ 117 | ((xtal_cpu) / ((baud_rate) * 16l) - 1) 118 | 119 | /** @brief UART Baudrate Expression for ATmega double speed mode 120 | * @param xtalcpu system clock in Mhz, e.g. 4000000L for 4Mhz 121 | * @param baudrate baudrate in bps, e.g. 1200, 2400, 9600 122 | */ 123 | #define UART_BAUD_SELECT_DOUBLE_SPEED(baud_rate, xtal_cpu) \ 124 | (((xtal_cpu) / ((baud_rate) * 8l) - 1) | UART_BAUD_RATE_2X) 125 | 126 | 127 | /** Default size of the circular receive buffers, must be power of 2 */ 128 | #define UART_RX_BUFFER_SIZE 32 129 | 130 | /** Default size of the circular transmit buffers, must be power of 2 */ 131 | #define UART_TX_BUFFER_SIZE 32 132 | 133 | /* size of RX/TX buffers */ 134 | #define UART_RX_BUFFER_MASK ( UART_RX_BUFFER_SIZE - 1) 135 | #define UART_TX_BUFFER_MASK ( UART_TX_BUFFER_SIZE - 1) 136 | 137 | #if ( UART_RX_BUFFER_SIZE & UART_RX_BUFFER_MASK ) 138 | #error "UART_RX_BUFFER_SIZE must be a power of two!" 139 | #endif 140 | #if ( UART_TX_BUFFER_SIZE & UART_TX_BUFFER_MASK ) 141 | #error "UART_TX_BUFFER_SIZE must be a power of two!" 142 | #endif 143 | 144 | /* Test if the size of the circular buffers fits into SRAM */ 145 | #if ( (UART_RX_BUFFER_SIZE+UART_TX_BUFFER_SIZE) >= (RAMEND-0x60 ) ) 146 | #error "Size of UART_RX_BUFFER_SIZE + UART_TX_BUFFER_SIZE larger than size of SRAM" 147 | #endif 148 | 149 | /* 150 | ** High byte error return code of uart_getc() 151 | */ 152 | #define UART_FRAME_ERROR 0x0800 /* Framing Error by UART */ 153 | #define UART_OVERRUN_ERROR 0x0400 /* Overrun condition by UART */ 154 | #define UART_BUFFER_OVERFLOW 0x0200 /* Receive ringbuffer overflow */ 155 | #define UART_NO_DATA 0x0100 /* No receive data available */ 156 | 157 | /**@}*/ 158 | 159 | #endif // UART_H 160 | 161 | -------------------------------------------------------------------------------- /uart/uart_description.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Jeremy Cole 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program 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. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | */ 19 | 20 | #include "uart_description.h" 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include "uart_quirks.h" 27 | 28 | #define UARTX_DESCRIPTION(name, suffix) \ 29 | { name, \ 30 | { \ 31 | &UCSR##suffix##A, \ 32 | &UCSR##suffix##B, \ 33 | &UCSR##suffix##C, \ 34 | &UDR##suffix, \ 35 | &UBRR##suffix##H, \ 36 | &UBRR##suffix##L \ 37 | }, \ 38 | (_BV(RXCIE##suffix) | _BV(RXEN##suffix)| _BV(TXEN##suffix)), \ 39 | _BV(UDRIE##suffix), \ 40 | _BV(U2X##suffix), \ 41 | 0, \ 42 | (_BV(UCSZ##suffix##1) | _BV(UCSZ##suffix##0)), \ 43 | _BV(FE##suffix), \ 44 | _BV(DOR##suffix) \ 45 | } 46 | 47 | 48 | uart_description_t uart_descriptions[] = { 49 | 50 | #if defined(UART0_STATUS) 51 | { "0", 52 | { 53 | &UART0_STATUS, 54 | &UART0_CONTROL, 55 | &UART0_FORMAT, 56 | &UART0_DATA, 57 | &UART0_UBRRH, 58 | &UART0_UBRRL 59 | }, 60 | UART0_ENABLE, 61 | UART0_UDRIE, 62 | UART0_U2X, 63 | 0, 64 | UART0_FORMAT_8N1, 65 | UART0_ERROR_FE, 66 | UART0_ERROR_DOR 67 | }, 68 | #endif 69 | 70 | #if defined(UDRIE1) 71 | UARTX_DESCRIPTION("1", 1), 72 | #endif 73 | 74 | #if defined(UDRIE2) 75 | UARTX_DESCRIPTION("2", 2), 76 | #endif 77 | 78 | #if defined(UDRIE3) 79 | UARTX_DESCRIPTION("3", 3), 80 | #endif 81 | 82 | { NULL, {NULL, NULL, NULL, NULL, NULL, NULL}, 0, 0, 0, 0, 0, 0 } 83 | }; 84 | 85 | -------------------------------------------------------------------------------- /uart/uart_description.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Jeremy Cole 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program 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. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | */ 19 | #ifndef UART_DESCRIPTION_H 20 | #define UART_DESCRIPTION_H 21 | 22 | #include 23 | #include 24 | 25 | typedef struct _uart_registers_t 26 | { 27 | volatile uint8_t *status; 28 | volatile uint8_t *control; 29 | volatile uint8_t *format; 30 | volatile uint8_t *data; 31 | volatile uint8_t *baud_h; 32 | volatile uint8_t *baud_l; 33 | } uart_registers_t; 34 | 35 | typedef struct _uart_description_t 36 | { 37 | char *name; 38 | uart_registers_t registers; 39 | uint8_t control_enable; 40 | uint8_t control_udrie; 41 | uint8_t status_u2x; 42 | uint8_t format_async; 43 | uint8_t format_8n1; 44 | uint8_t error_fe; 45 | uint8_t error_dor; 46 | } uart_description_t; 47 | 48 | 49 | extern uart_description_t uart_descriptions[]; 50 | 51 | #endif /* UART_DESCRIPTION_H */ 52 | -------------------------------------------------------------------------------- /uart/uart_quirks.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Jeremy Cole 3 | Copyright (c) 2006, Peter Fleury 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | */ 20 | 21 | #ifndef UART_QUIRKS_H 22 | #define UART_QUIRKS_H 23 | 24 | #include 25 | 26 | /* 27 | * Old AVR AT90 classic or ATmega103 with one UART. 28 | * - Status/Control Registers: Split USR/UCR 29 | * - Numeric Suffixes on Regs: No 30 | * - Numeric Suffixes on ISRs: No 31 | */ 32 | #if defined(__AVR_AT90S2313__) \ 33 | || defined(__AVR_AT90S4414__) \ 34 | || defined(__AVR_AT90S4434__) \ 35 | || defined(__AVR_AT90S8515__) \ 36 | || defined(__AVR_AT90S8535__) \ 37 | || defined(__AVR_ATmega103__) 38 | 39 | #define UART0_PRESENT 1 40 | #define UART0_RXC_INT UART_RX_vect 41 | #define UART0_TXC_INT UART_TX_vect 42 | #define UART0_DRE_INT UART_UDRE_vect 43 | #define UART0_STATUS USR 44 | #define UART0_CONTROL UCR 45 | #define UART0_DATA UDR 46 | #define UART0_UBRRL UBRR 47 | #undef UART0_UBRRH 48 | #define UART0_UDRIE _BV(UDRIE) 49 | #undef UART0_U2X 50 | #undef UART0_ENABLE 51 | #define UART0_FORMAT_8N1 (_BV(UCSZ01) | _BV(UCSZ00)) 52 | #define UART0_ERROR_FE _BV(FE) 53 | #define UART0_ERROR_DOR _BV(DOR) 54 | 55 | /* 56 | * Old AVR AT90 classic with one UART. 57 | * - Status/Control Registers: Combined A/B 58 | * - Numeric Suffixes on Regs: No 59 | * - Numeric Suffixes on ISRs: No 60 | */ 61 | #elif defined(__AVR_AT90S2333__) \ 62 | || defined(__AVR_AT90S4433__) 63 | 64 | #define UART0_RXC_INT UART_RX_vect 65 | #define UART0_TXC_INT UART_TX_vect 66 | #define UART0_DRE_INT UART_UDRE_vect 67 | #define UART0_STATUS UCSRA 68 | #define UART0_CONTROL UCSRB 69 | #define UART0_FORMAT UCSRC 70 | #define UART0_DATA UDR 71 | #define UART0_UBRRL UBRR 72 | #undef UART0_UBRRH 73 | #define UART0_UDRIE _BV(UDRIE) 74 | #undef UART0_U2X 75 | #undef UART0_ENABLE 76 | #define UART0_FORMAT_8N1 (_BV(UCSZ1) | _BV(UCSZ0)) 77 | #define UART0_ERROR_FE _BV(FE) 78 | #define UART0_ERROR_DOR _BV(DOR) 79 | 80 | /* ATmega with one UART/USART 81 | * - Status/Control Registers: Combined A/B 82 | * - Numeric Suffixes on Regs: No 83 | * - Numeric Suffixes on ISRs: No 84 | */ 85 | #elif defined(__AVR_ATmega8__) \ 86 | || defined(__AVR_ATmega16__) \ 87 | || defined(__AVR_ATmega32__) \ 88 | || defined(__AVR_ATmega323__) \ 89 | || defined(__AVR_ATmega8515__) \ 90 | || defined(__AVR_ATmega8535__) \ 91 | || defined(__AVR_ATtiny2313__) \ 92 | || defined(__AVR_ATmega163__) \ 93 | || defined(__AVR_ATmega169__) 94 | 95 | #undef UART0_RXC_INT 96 | #undef UART0_TXC_INT 97 | #undef UART0_DRE_INT 98 | #define UART0_STATUS UCSRA 99 | #define UART0_CONTROL UCSRB 100 | #define UART0_FORMAT UCSRC 101 | #define UART0_DATA UDR 102 | #if defined(UBRRHI) 103 | /* This is a UART, not a USART */ 104 | #define UART0_UBRRL UBRR 105 | #define UART0_UBRRH UBRRHI 106 | #else 107 | #define UART0_UBRRL UBRRL 108 | #define UART0_UBRRH UBRRH 109 | #endif 110 | #define UART0_UDRIE _BV(UDRIE) 111 | #define UART0_U2X _BV(U2X) 112 | #define UART0_ENABLE (_BV(RXCIE) | _BV(RXEN)| _BV(TXEN)) 113 | #define UART0_FORMAT_8N1 (_BV(UCSZ1) | _BV(UCSZ0)) 114 | #define UART0_ERROR_FE _BV(FE) 115 | #define UART0_ERROR_DOR _BV(DOR) 116 | 117 | /* ATmega with one USART 118 | * - Status/Control Registers: Combined A/B 119 | * - Numeric Suffixes on Regs: Yes 120 | * - Numeric Suffixes on ISRs: Yes 121 | */ 122 | #elif defined(__AVR_ATmega48__) \ 123 | || defined(__AVR_ATmega88__) \ 124 | || defined(__AVR_ATmega168__) \ 125 | || defined(__AVR_ATmega329__) \ 126 | || defined(__AVR_ATmega3290__) \ 127 | || defined(__AVR_ATmega649__) \ 128 | || defined(__AVR_ATmega6490__) \ 129 | || defined(__AVR_ATmega325__) \ 130 | || defined(__AVR_ATmega3250__) \ 131 | || defined(__AVR_ATmega645__) \ 132 | || defined(__AVR_ATmega6450__) \ 133 | || defined(__AVR_ATmega644__) 134 | 135 | #undef UART0_RXC_INT 136 | #undef UART0_TXC_INT 137 | #undef UART0_DRE_INT 138 | #define UART0_STATUS UCSR0A 139 | #define UART0_CONTROL UCSR0B 140 | #define UART0_FORMAT UCSR0C 141 | #define UART0_DATA UDR0 142 | #define UART0_UBRRL UBRR0L 143 | #define UART0_UBRRH UBRR0H 144 | #define UART0_UDRIE _BV(UDRIE0) 145 | #define UART0_U2X _BV(U2X0) 146 | #define UART0_ENABLE (_BV(RXCIE0) | _BV(RXEN0)| _BV(TXEN0)) 147 | #define UART0_FORMAT_8N1 (_BV(UCSZ01) | _BV(UCSZ00)) 148 | #define UART0_ERROR_FE _BV(FE0) 149 | #define UART0_ERROR_DOR _BV(DOR0) 150 | 151 | /* ATmega with two USART */ 152 | #elif defined(__AVR_ATmega162__) \ 153 | || defined(__AVR_ATmega64__) \ 154 | || defined(__AVR_ATmega128__) \ 155 | || defined(__AVR_ATmega2560__) \ 156 | || defined(__AVR_ATmega1280__) \ 157 | || defined(__AVR_ATmega640__) \ 158 | || defined(__AVR_ATmega164P__) \ 159 | || defined(__AVR_ATmega324P__) \ 160 | || defined(__AVR_ATmega644P__) \ 161 | || defined(__AVR_ATmega1284P__) 162 | 163 | #undef UART0_RXC_INT 164 | #undef UART0_TXC_INT 165 | #undef UART0_DRE_INT 166 | #define UART0_STATUS UCSR0A 167 | #define UART0_CONTROL UCSR0B 168 | #define UART0_FORMAT UCSR0C 169 | #define UART0_DATA UDR0 170 | #define UART0_UBRRL UBRR0L 171 | #define UART0_UBRRH UBRR0H 172 | #define UART0_UDRIE _BV(UDRIE0) 173 | #define UART0_U2X _BV(U2X0) 174 | #define UART0_ENABLE (_BV(RXCIE0) | _BV(RXEN0)| _BV(TXEN0)) 175 | #define UART0_FORMAT_8N1 (_BV(UCSZ01) | _BV(UCSZ00)) 176 | #define UART0_ERROR_FE _BV(FE0) 177 | #define UART0_ERROR_DOR _BV(DOR0) 178 | 179 | #else 180 | #error "No UART definition for MCU available" 181 | #endif 182 | 183 | #if !defined(USART0_RXC_INT) 184 | #if defined(USART0_RX_vect) 185 | #define UART0_RXC_INT USART0_RX_vect 186 | #elif defined(USART_RX_vect) 187 | #define UART0_RXC_INT USART_RX_vect 188 | #elif defined(UART0_RXC_vect) 189 | #define UART0_RXC_INT USART0_RXC_vect 190 | #elif defined(UART_RXC_vect) 191 | #define UART0_RXC_INT USART_RXC_vect 192 | #else 193 | #error "Couldn't find a usable interrupt vector for UART0_RXC_INT!" 194 | #endif 195 | #endif 196 | 197 | #if !defined(USART0_TXC_INT) 198 | #if defined(USART0_TX_vect) 199 | #define UART0_TXC_INT USART0_TX_vect 200 | #elif defined(USART_TX_vect) 201 | #define UART0_TXC_INT USART_TX_vect 202 | #elif defined(UART0_TXC_vect) 203 | #define UART0_TXC_INT USART0_TXC_vect 204 | #elif defined(UART_TXC_vect) 205 | #define UART0_TXC_INT USART_TXC_vect 206 | #else 207 | #error "Couldn't find a usable interrupt vector for UART0_TXC_INT!" 208 | #endif 209 | #endif 210 | 211 | #if !defined(USART0_DRE_INT) 212 | #if defined(USART0_UDRE_vect) 213 | #define UART0_DRE_INT USART0_UDRE_vect 214 | #elif defined(USART_UDRE_vect) 215 | #define UART0_DRE_INT USART_UDRE_vect 216 | #else 217 | #error "Couldn't find a usable interrupt vector for UART0_DRE_INT!" 218 | #endif 219 | #endif 220 | 221 | #endif /* UART_QUIRKS_H */ 222 | -------------------------------------------------------------------------------- /uart_test/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | uart_test 4 | 5 | 6 | uart 7 | 8 | 9 | 10 | org.eclipse.cdt.managedbuilder.core.genmakebuilder 11 | clean,full,incremental, 12 | 13 | 14 | ?name? 15 | 16 | 17 | 18 | org.eclipse.cdt.make.core.append_environment 19 | true 20 | 21 | 22 | org.eclipse.cdt.make.core.autoBuildTarget 23 | all 24 | 25 | 26 | org.eclipse.cdt.make.core.buildArguments 27 | 28 | 29 | 30 | org.eclipse.cdt.make.core.buildCommand 31 | make 32 | 33 | 34 | org.eclipse.cdt.make.core.buildLocation 35 | ${workspace_loc:/uart_test/Release} 36 | 37 | 38 | org.eclipse.cdt.make.core.cleanBuildTarget 39 | clean 40 | 41 | 42 | org.eclipse.cdt.make.core.contents 43 | org.eclipse.cdt.make.core.activeConfigSettings 44 | 45 | 46 | org.eclipse.cdt.make.core.enableAutoBuild 47 | false 48 | 49 | 50 | org.eclipse.cdt.make.core.enableCleanBuild 51 | true 52 | 53 | 54 | org.eclipse.cdt.make.core.enableFullBuild 55 | true 56 | 57 | 58 | org.eclipse.cdt.make.core.fullBuildTarget 59 | all 60 | 61 | 62 | org.eclipse.cdt.make.core.stopOnError 63 | true 64 | 65 | 66 | org.eclipse.cdt.make.core.useDefaultBuildCmd 67 | true 68 | 69 | 70 | 71 | 72 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder 73 | 74 | 75 | 76 | 77 | 78 | org.eclipse.cdt.core.cnature 79 | org.eclipse.cdt.managedbuilder.core.managedBuildNature 80 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature 81 | de.innot.avreclipse.core.avrnature 82 | 83 | 84 | -------------------------------------------------------------------------------- /uart_test/.settings/de.innot.avreclipse.core.prefs: -------------------------------------------------------------------------------- 1 | avrtarget/ClockFrequency=8000000 2 | avrtarget/ExtRAMSize=0 3 | avrtarget/ExtendedRAM=false 4 | avrtarget/MCUType=atmega1284p 5 | avrtarget/UseEEPROM=false 6 | avrtarget/UseExtendedRAMforHeap=true 7 | avrtarget/avrdude/BitBangDelay= 8 | avrtarget/avrdude/Bitclock= 9 | avrtarget/avrdude/EEPROMFile= 10 | avrtarget/avrdude/EEPROMFromConfig=true 11 | avrtarget/avrdude/FlashFile= 12 | avrtarget/avrdude/FlashFromConfig=true 13 | avrtarget/avrdude/Fuses/ByteValues=194\:217\:255 14 | avrtarget/avrdude/Fuses/FileName= 15 | avrtarget/avrdude/Fuses/MCUid=atmega644 16 | avrtarget/avrdude/Fuses/UseFile=false 17 | avrtarget/avrdude/Fuses/Write=true 18 | avrtarget/avrdude/NoChipErase=false 19 | avrtarget/avrdude/NoSigCheck=false 20 | avrtarget/avrdude/NoVerify=false 21 | avrtarget/avrdude/NoWrite=false 22 | avrtarget/avrdude/OtherOptions= 23 | avrtarget/avrdude/ProgrammerID=programmerconfig.1 24 | avrtarget/avrdude/UseCounter=false 25 | avrtarget/avrdude/WriteEEPROM=false 26 | avrtarget/avrdude/WriteFlash=true 27 | avrtarget/perConfig=false 28 | eclipse.preferences.version=1 29 | -------------------------------------------------------------------------------- /uart_test/uart_test.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Jeremy Cole 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program 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. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include 30 | 31 | void uart_dump() 32 | { 33 | uart_description_t *d; 34 | for(d=uart_descriptions; d->name; d++) 35 | { 36 | printf("UART: %s\n", d->name); 37 | printf(" status: %02x u2x: %02x\n", 38 | (unsigned int)d->registers.status, 39 | d->status_u2x); 40 | printf(" control: %02x enable: %02x udrie: %02x\n", 41 | (unsigned int)d->registers.control, 42 | d->control_enable, 43 | d->control_udrie); 44 | printf(" format: %02x 8n1: %02x\n", 45 | (unsigned int)d->registers.format, 46 | d->format_8n1); 47 | printf(" data: %02x\n", (unsigned int)d->registers.data); 48 | printf(" baud_h: %02x\n", (unsigned int)d->registers.baud_h); 49 | printf(" baud_l: %02x\n", (unsigned int)d->registers.baud_l); 50 | printf("\n"); 51 | } 52 | } 53 | 54 | int main(void) 55 | { 56 | uart_t *u0; 57 | //uart_t *u1; 58 | _delay_ms(1000); 59 | 60 | u0 = uart_init("0", UART_BAUD_SELECT(9600, F_CPU)); 61 | //u1 = uart_init("1", 0); 62 | uart_init_stdout(u0); 63 | 64 | sei(); 65 | 66 | uart_puts(u0, "\r\n\r\nBooted up!\r\n"); 67 | 68 | uart_dump(); 69 | 70 | while(1) 71 | { 72 | uart_puts(u0, "Test on UART 0!\r\n"); 73 | //uart_puts(u1, "Test on UART 1!\r\n"); 74 | _delay_ms(100); 75 | } 76 | 77 | return(0); 78 | } 79 | --------------------------------------------------------------------------------