├── .gitignore ├── Makefile ├── README.md ├── eeprom └── eeprom_settings.txt ├── main.c └── rpi-sense.S /.gitignore: -------------------------------------------------------------------------------- 1 | src 2 | *.hex 3 | *.o 4 | *.lst 5 | *.bin 6 | *.elf 7 | *.map 8 | *.srec 9 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PRG = rpi-sense 2 | OBJ = main.o rpi-sense.o 3 | 4 | MCU_TARGET = attiny88 5 | 6 | OPTIMIZE = -Os 7 | 8 | CC = avr-gcc 9 | 10 | # Override is only needed by avr-lib build system. 11 | 12 | override ASFLAGS = -Wall -mmcu=$(MCU_TARGET) 13 | override CFLAGS = -g -Wall $(OPTIMIZE) -mmcu=$(MCU_TARGET) $(DEFS) 14 | override LDFLAGS = -Wl,-Map,$(PRG).map 15 | 16 | OBJCOPY = avr-objcopy 17 | OBJDUMP = avr-objdump 18 | 19 | all: $(PRG).elf lst text eeprom 20 | 21 | $(PRG).elf: $(OBJ) 22 | $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS) 23 | 24 | # Dependencies 25 | main.o: main.c 26 | rpi-sense.o: rpi-sense.S 27 | 28 | .PHONY: clean 29 | clean: 30 | rm -rf *.o $(PRG).elf *.eps *.png *.pdf *.bak 31 | rm -rf *.lst *.map $(EXTRA_CLEAN_FILES) 32 | 33 | lst: $(PRG).lst 34 | 35 | %.lst: %.elf 36 | $(OBJDUMP) -h -S $< > $@ 37 | 38 | # Rules for building the .text rom images 39 | 40 | text: hex bin srec 41 | 42 | hex: $(PRG).hex 43 | bin: $(PRG).bin 44 | srec: $(PRG).srec 45 | 46 | %.hex: %.elf 47 | $(OBJCOPY) -j .text -j .data -O ihex $< $@ 48 | 49 | %.srec: %.elf 50 | $(OBJCOPY) -j .text -j .data -O srec $< $@ 51 | 52 | %.bin: %.elf 53 | $(OBJCOPY) -j .text -j .data -O binary $< $@ 54 | 55 | # Rules for building the .eeprom rom images 56 | 57 | eeprom: ehex ebin esrec 58 | 59 | ehex: $(PRG)_eeprom.hex 60 | ebin: $(PRG)_eeprom.bin 61 | esrec: $(PRG)_eeprom.srec 62 | 63 | %_eeprom.hex: %.elf 64 | $(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O ihex $< $@ \ 65 | || { echo empty $@ not generated; exit 0; } 66 | 67 | %_eeprom.srec: %.elf 68 | $(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O srec $< $@ \ 69 | || { echo empty $@ not generated; exit 0; } 70 | 71 | %_eeprom.bin: %.elf 72 | $(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O binary $< $@ \ 73 | || { echo empty $@ not generated; exit 0; } 74 | 75 | # Every thing below here is used by avr-libc's build system and can be ignored 76 | # by the casual user. 77 | 78 | FIG2DEV = fig2dev 79 | EXTRA_CLEAN_FILES = *.hex *.bin *.srec 80 | 81 | dox: eps png pdf 82 | 83 | eps: $(PRG).eps 84 | png: $(PRG).png 85 | pdf: $(PRG).pdf 86 | 87 | %.eps: %.fig 88 | $(FIG2DEV) -L eps $< $@ 89 | 90 | %.pdf: %.fig 91 | $(FIG2DEV) -L pdf $< $@ 92 | 93 | %.png: %.fig 94 | $(FIG2DEV) -L png $< $@ 95 | 96 | # Flash 97 | flash: $(PRG).hex 98 | sudo avrdude -c linuxspi -p t88 -P /dev/spidev0.0 -U flash:w:$(PRG).hex 99 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RPi-Sense 2 | 3 | WIP LED HAT firmware and driver 4 | 5 | ## Prerequisites 6 | 7 | `sudo apt-get install gcc-avr avr-libc avrdude` 8 | 9 | ## Compiling 10 | 11 | `make` 12 | 13 | ## Flashing 14 | 15 | Ensure SPI is enabled. 16 | 17 | `make flash` 18 | 19 | ## Using the board 20 | 21 | Enable I2C in `raspi-config` 22 | 23 | Boards with a programmed EEPROM will have nodes populated in the device tree automatically. 24 | 25 | Add the following module to `/etc/modules`: 26 | 27 | ``` 28 | i2c-dev 29 | ``` 30 | 31 | ## Using IIO 32 | 33 | https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-bus-iio 34 | 35 | https://archive.fosdem.org/2012/schedule/event/693/127_iio-a-new-subsystem.pdf 36 | 37 | http://wiki.analog.com/software/linux/docs/iio/iio-trig-sysfs 38 | -------------------------------------------------------------------------------- /eeprom/eeprom_settings.txt: -------------------------------------------------------------------------------- 1 | ######################################################################## 2 | # EEPROM settings text file 3 | # 4 | # Edit this file for your particular board and run through eepmake tool, 5 | # then use eepflash tool to write to attached HAT ID EEPROM 6 | # 7 | # Tools available: 8 | # eepmake Parses EEPROM text file and creates binary .eep file 9 | # eepdump Dumps a binary .eep file as human readable text (for debug) 10 | # eepflash Write or read .eep binary image to/from HAT EEPROM 11 | # 12 | ######################################################################## 13 | 14 | ######################################################################## 15 | # Vendor info 16 | 17 | # 128 bit UUID. If left at zero eepmake tool will auto-generate 18 | # RFC 4122 compliant UUID 19 | product_uuid 00000000-0000-0000-0000-000000000000 20 | 21 | # 16 bit product id 22 | product_id 0x0001 23 | 24 | # 16 bit product version 25 | product_ver 0x0001 26 | 27 | # ASCII vendor string (max 255 characters) 28 | vendor "Raspberry Pi" 29 | 30 | # ASCII product string (max 255 characters) 31 | product "Sense HAT" 32 | 33 | 34 | ######################################################################## 35 | # GPIO bank settings, set to nonzero to change from the default. 36 | # NOTE these setting can only be set per BANK, uncommenting any of 37 | # these will force the bank to use the custom setting. 38 | 39 | # drive strength, 0=default, 1-8=2,4,6,8,10,12,14,16mA, 9-15=reserved 40 | gpio_drive 0 41 | 42 | # 0=default, 1=slew rate limiting, 2=no slew limiting, 3=reserved 43 | gpio_slew 0 44 | 45 | # 0=default, 1=hysteresis disabled, 2=hysteresis enabled, 3=reserved 46 | gpio_hysteresis 0 47 | 48 | # If board back-powers Pi via 5V GPIO header pins: 49 | # 0 = board does not back-power 50 | # 1 = board back-powers and can supply the Pi with a minimum of 1.3A 51 | # 2 = board back-powers and can supply the Pi with a minimum of 2A 52 | # 3 = reserved 53 | # If back_power=2 then USB high current mode will be automatically 54 | # enabled on the Pi 55 | back_power 0 56 | 57 | ######################################################################## 58 | # GPIO pins, uncomment for GPIOs used on board 59 | # Options for FUNCTION: INPUT, OUTPUT, ALT0-ALT5 60 | # Options for PULL: DEFAULT, UP, DOWN, NONE 61 | # NB GPIO0 and GPIO1 are reserved for ID EEPROM so cannot be set 62 | 63 | # GPIO FUNCTION PULL 64 | # ---- -------- ---- 65 | #setgpio 2 INPUT DEFAULT 66 | #setgpio 3 INPUT DEFAULT 67 | #setgpio 4 INPUT DEFAULT 68 | #setgpio 5 INPUT DEFAULT 69 | #setgpio 6 INPUT DEFAULT 70 | #setgpio 7 INPUT DEFAULT 71 | #setgpio 8 INPUT DEFAULT 72 | #setgpio 9 INPUT DEFAULT 73 | #setgpio 10 INPUT DEFAULT 74 | #setgpio 11 INPUT DEFAULT 75 | #setgpio 12 INPUT DEFAULT 76 | #setgpio 13 INPUT DEFAULT 77 | #setgpio 14 INPUT DEFAULT 78 | #setgpio 15 INPUT DEFAULT 79 | #setgpio 16 INPUT DEFAULT 80 | #setgpio 17 INPUT DEFAULT 81 | #setgpio 18 INPUT DEFAULT 82 | #setgpio 19 INPUT DEFAULT 83 | #setgpio 20 INPUT DEFAULT 84 | #setgpio 21 INPUT DEFAULT 85 | #setgpio 22 INPUT DEFAULT 86 | #setgpio 23 INPUT DEFAULT 87 | #setgpio 24 INPUT DEFAULT 88 | #setgpio 25 INPUT DEFAULT 89 | #setgpio 26 INPUT DEFAULT 90 | #setgpio 27 INPUT DEFAULT 91 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * main.c - Atmel main loop for LED matrix driving 3 | * 4 | * Copyright (c) 2015 Raspberry Pi Foundation 5 | * 6 | * Author: Serge Schneider 7 | * All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions are met: 11 | * * Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * * Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * * Neither the name of Raspberry Pi nor the 17 | * names of its contributors may be used to endorse or promote products 18 | * derived from this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 21 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 22 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 24 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 25 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 27 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | #define EE_WP (1 << PB0) 39 | #define KEYS_INT (1 << PB6) 40 | #define FRAME_INT (1 << PB7) 41 | 42 | #define LED_SDO (1 << PC0) 43 | #define LED_CLKR (1 << PC1) 44 | #define LED_LE (1 << PC2) 45 | #define LED_SDI (1 << PC3) 46 | #define LED_OE_N (1 << PC7) 47 | 48 | #define set(port,x) port |= (x) 49 | #define clr(port,x) port &= ~(x) 50 | 51 | extern void draw_loop(); 52 | extern void clear_gain(void); 53 | extern void delay(uint8_t ticks); 54 | extern void write_data(uint32_t data, char type); 55 | 56 | enum REG_ADDR { 57 | REG_ID = 192, 58 | REG_CFG_LOW, 59 | REG_CFG_HIGH, 60 | }; 61 | 62 | typedef enum { 63 | DAT_LATCH = 22, 64 | CONF_WRITE = 20, 65 | CONF_READ = 18, 66 | GAIN_WRITE = 16, 67 | GAIN_READ = 14, 68 | DET_OPEN = 13, 69 | DET_SHORT = 12, 70 | DET_OPEN_SHORT = 11, 71 | THERM_READ = 10, 72 | } le_key; 73 | 74 | volatile uint8_t pixels[] = { 75 | 0x1F, 0x1F, 0x1F, 0x1F, 0x14, 0x03, 0x00, 0x00, 76 | 0x00, 0x00, 0x03, 0x12, 0x1F, 0x1F, 0x1F, 0x1F, 77 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 78 | 79 | 0x1F, 0x1F, 0x1F, 0x12, 0x03, 0x00, 0x00, 0x00, 80 | 0x00, 0x04, 0x14, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 81 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x1D, 82 | 83 | 0x1F, 0x1F, 0x11, 0x02, 0x00, 0x00, 0x00, 0x00, 84 | 0x05, 0x15, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x0B, 85 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x1F, 0x1F, 86 | 87 | 0x1F, 0x0F, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 88 | 0x17, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x0A, 0x00, 89 | 0x00, 0x00, 0x00, 0x00, 0x0A, 0x1F, 0x1F, 0x1F, 90 | 91 | 0x0E, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 92 | 0x1F, 0x1F, 0x1F, 0x1F, 0x1D, 0x08, 0x00, 0x00, 93 | 0x00, 0x00, 0x01, 0x0B, 0x1F, 0x1F, 0x1F, 0x1F, 94 | 95 | 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x14, 96 | 0x1F, 0x1F, 0x1F, 0x1B, 0x07, 0x00, 0x00, 0x00, 97 | 0x00, 0x01, 0x0C, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 98 | 99 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x15, 0x1F, 100 | 0x1F, 0x1F, 0x19, 0x06, 0x00, 0x00, 0x00, 0x00, 101 | 0x02, 0x0E, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x12, 102 | 103 | 0x00, 0x00, 0x00, 0x00, 0x05, 0x17, 0x1F, 0x1F, 104 | 0x1F, 0x17, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 105 | 0x0F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x0F, 0x02, 106 | }; 107 | 108 | volatile char keys; 109 | volatile char i2c_reg = 0xff; 110 | 111 | int main(void) 112 | { 113 | PORTA = 0; 114 | PORTB = 1; 115 | PORTC = 0; 116 | PORTD = 0xFF; 117 | DDRB = EE_WP | FRAME_INT | KEYS_INT; 118 | DDRC = LED_SDI | LED_CLKR | LED_LE | LED_OE_N; 119 | DDRD = 0xFF; 120 | 121 | TCCR0A = (1< 7 | * All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions are met: 11 | * * Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * * Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * * Neither the name of Raspberry Pi nor the 17 | * names of its contributors may be used to endorse or promote products 18 | * derived from this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 21 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 22 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 24 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 25 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 27 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | 32 | #include 33 | #include 34 | 35 | LINE = 24 36 | PARAM = 24 37 | PWM = 25 38 | I2C_OFF = 26 ; XL 39 | 40 | .equiv I2C_WAI , 0xf0 41 | .equiv I2C_VER , 0xf1 42 | .equiv I2C_KEYS , 0xf2 43 | .equiv I2C_EE_WP, 0xf3 44 | .equiv I2C_ID , 's' 45 | .equiv VERSION , 0 46 | 47 | ; PORTB 48 | .equiv EE_WP , PB0 49 | .equiv KEYS_INT , PB6 50 | .equiv FRAME_INT, PB7 51 | 52 | ; PORTC 53 | .equiv LED_SDO , PC0 54 | .equiv LED_CLKR , PC1 55 | .equiv LED_LE , PC2 56 | .equiv LED_SDI , PC3 57 | .equiv SDA , PC4 58 | .equiv SCL , PC5 59 | .equiv LED_OE_N , PC7 60 | 61 | .macro CLOCK_OUT 62 | SBI _SFR_IO_ADDR(PORTC), LED_CLKR 63 | CBI _SFR_IO_ADDR(PORTC), LED_CLKR 64 | .endm 65 | 66 | .macro COL_OUT reg 67 | CP PWM, \reg 68 | BRSH lclear\reg 69 | SBI _SFR_IO_ADDR(PORTC), LED_SDI 70 | RJMP ldone\reg 71 | lclear\reg: 72 | CBI _SFR_IO_ADDR(PORTC), LED_SDI 73 | ldone\reg: 74 | CLOCK_OUT 75 | .endm 76 | 77 | .global draw_loop 78 | .global delay 79 | .global read_data 80 | .global write_data 81 | .global TWI_vect 82 | 83 | .extern pixels 84 | .extern id 85 | .extern key 86 | .extern i2c_reg 87 | 88 | .section .text 89 | .func draw_loop 90 | draw_loop: 91 | Lframe_loop: 92 | CBI _SFR_IO_ADDR(PORTC), FRAME_INT 93 | LDI YL, lo8(pixels) 94 | LDI YH, hi8(pixels) 95 | LDI LINE, 0xFE 96 | Lline_loop: 97 | OUT _SFR_IO_ADDR(PORTD), LINE 98 | LDI PWM, 0 99 | LD r0, Y+ 100 | LD r1, Y+ 101 | LD r2, Y+ 102 | LD r3, Y+ 103 | LD r4, Y+ 104 | LD r5, Y+ 105 | LD r6, Y+ 106 | LD r7, Y+ 107 | LD r8, Y+ 108 | LD r9, Y+ 109 | LD r10, Y+ 110 | LD r11, Y+ 111 | LD r12, Y+ 112 | LD r13, Y+ 113 | LD r14, Y+ 114 | LD r15, Y+ 115 | LD r16, Y+ 116 | LD r17, Y+ 117 | LD r18, Y+ 118 | LD r19, Y+ 119 | LD r20, Y+ 120 | LD r21, Y+ 121 | LD r22, Y+ 122 | LD r23, Y+ 123 | Lpwm_loop: 124 | COL_OUT r0 125 | COL_OUT r1 126 | COL_OUT r2 127 | COL_OUT r3 128 | COL_OUT r4 129 | COL_OUT r5 130 | COL_OUT r6 131 | COL_OUT r7 132 | COL_OUT r8 133 | COL_OUT r9 134 | COL_OUT r10 135 | COL_OUT r11 136 | COL_OUT r12 137 | COL_OUT r13 138 | COL_OUT r14 139 | COL_OUT r15 140 | COL_OUT r16 141 | COL_OUT r17 142 | COL_OUT r18 143 | COL_OUT r19 144 | COL_OUT r20 145 | COL_OUT r21 146 | SBI _SFR_IO_ADDR(PORTC), LED_LE 147 | COL_OUT r22 148 | COL_OUT r23 149 | CBI _SFR_IO_ADDR(PORTC), LED_LE 150 | INC PWM 151 | SBRS PWM, 6 152 | RJMP Lpwm_loop 153 | ROL LINE 154 | BRCC lframeend 155 | INC LINE 156 | RJMP Lline_loop 157 | lframeend: 158 | SBI _SFR_IO_ADDR(PORTB), FRAME_INT 159 | CBI _SFR_IO_ADDR(PORTD), 7 ; Clear PORTD 160 | 161 | SBI _SFR_IO_ADDR(PORTB), LED_OE_N ; Scan 162 | LDI PARAM, 0xF8 163 | OUT _SFR_IO_ADDR(PORTD), PARAM 164 | COM PARAM 165 | OUT _SFR_IO_ADDR(DDRD), PARAM 166 | LDS PWM, keys 167 | IN PARAM, _SFR_IO_ADDR(PIND) 168 | COM PARAM 169 | LSR PARAM 170 | LSR PARAM 171 | LSR PARAM 172 | STS keys, PARAM 173 | CPSE PARAM, PWM 174 | SBI _SFR_IO_ADDR(PORTB), KEYS_INT 175 | LDI PARAM, 0xFF 176 | OUT _SFR_IO_ADDR(DDRD), PARAM 177 | COM PARAM 178 | OUT _SFR_IO_ADDR(PORTD), PARAM 179 | CBI _SFR_IO_ADDR(PORTB), LED_OE_N ; /Scan 180 | RJMP Lframe_loop 181 | RET 182 | .endfunc 183 | 184 | .func delay 185 | delay: 186 | PUSH r19 187 | PUSH r20 188 | IN r20, _SFR_IO_ADDR(TCNT0) ; start = TCNT0; 189 | lloop: 190 | IN r19, _SFR_IO_ADDR(TCNT0) ; do { 191 | SUB r19, r20 ; diff = TCNT0 - start; 192 | CP r19, LINE ; } while (diff < ticks); 193 | BRLO lloop 194 | POP r20 195 | POP r19 196 | RET 197 | .endfunc 198 | 199 | .func write_data 200 | ; r20-23 DATA 201 | ; r24 TYPE 202 | write_data: 203 | PUSH r18 204 | ;PUSH r20 205 | PUSH r21 206 | PUSH r22 207 | PUSH r23 208 | PUSH r24 209 | LDI r18, 24 ; 210 | 1: ; do { 211 | SBRS r23, 0 ; if (data&1) 212 | RJMP 2f 213 | SBI _SFR_IO_ADDR(PORTC), LED_SDI ; set LED_SDI; 214 | RJMP 3f 215 | 2: ; else 216 | CBI _SFR_IO_ADDR(PORTC), LED_SDI ; clr LED_SDI; 217 | 3: 218 | ASR r23 ; data <<= 1; 219 | ROR r22 220 | ROR r21 221 | ;ROR r20 ; Don't need? 222 | CP r24, r18 ; if (type == i) 223 | BRNE 4f 224 | SBI _SFR_IO_ADDR(PORTC), LED_LE ; set LDE_LE; 225 | 4: 226 | CLOCK_OUT 227 | DEC r18 ; i--; 228 | BRNE 1b ; } while (i!=0); 229 | CBI _SFR_IO_ADDR(PORTC), LED_LE ; clr LDE_LE 230 | POP r24 231 | POP r23 232 | POP r22 233 | POP r21 234 | ;POP r20 235 | POP r18 236 | RET 237 | .endfunc 238 | 239 | .func read_data 240 | ; r22-25 RETURN 241 | ; r24 TYPE 242 | read_data: 243 | PUSH r18 244 | PUSH r19 245 | ;PUSH r20 246 | PUSH r21 247 | PUSH r22 248 | PUSH r23 249 | PUSH r24 250 | LDI r18, 24 ; 251 | 1: ; do { 252 | IN r19, _SFR_IO_ADDR(PORTC) ; ret |= PINC&1; 253 | ANDI r19, LED_SDI 254 | 255 | 256 | SBRS r23, 0 ; if (data&1) 257 | RJMP 2f 258 | SBI _SFR_IO_ADDR(PORTC), LED_SDI ; set LED_SDI; 259 | RJMP 3f 260 | 2: ; else 261 | CBI _SFR_IO_ADDR(PORTC), LED_SDI ; clr LED_SDI; 262 | 3: 263 | ASR r23 ; data <<= 1; 264 | ROR r22 265 | ROR r21 266 | ;ROR r20 ; Don't need? 267 | 268 | 269 | CP r24, r18 ; if (type == i) 270 | BRNE 4f 271 | SBI _SFR_IO_ADDR(PORTC), LED_LE ; set LDE_LE; 272 | 4: 273 | CLOCK_OUT 274 | DEC r18 ; i--; 275 | BRNE 1b ; } while (i!=0); 276 | CBI _SFR_IO_ADDR(PORTC), LED_LE ; clr LDE_LE 277 | POP r24 278 | POP r23 279 | POP r22 280 | POP r21 281 | ;POP r20 282 | POP r19 283 | POP r18 284 | RET 285 | .endfunc 286 | 287 | ;TODO: Add reads and NACK bad addresses. 288 | ;PARAM (r24) - TWSR 289 | ;PWM (r25) - SREG 290 | ;DI2C/XL (r26) - Address 291 | .func TWI_vect 292 | TWI_vect: 293 | PUSH PARAM 294 | PUSH PWM 295 | PUSH YL 296 | PUSH YH 297 | PUSH I2C_OFF 298 | IN PWM, _SFR_IO_ADDR(SREG) 299 | LDS PARAM, TWSR 300 | ANDI PARAM, 0xF8 301 | LDS I2C_OFF, i2c_reg 302 | CPI PARAM, TW_ST_SLA_ACK ; Slave Receive ACK Address 303 | BREQ ltsend 304 | CPI PARAM, TW_SR_DATA_ACK ; Slave Receive Data 305 | BREQ lreceive 306 | CPI PARAM, TW_SR_SLA_ACK ; Slave Receive ACK Address 307 | BREQ lrack 308 | CPI PARAM, TW_ST_DATA_ACK ; Slave Transmit Data 309 | BREQ ltsend 310 | CPI PARAM, TW_ST_DATA_NACK 311 | BREQ ltdnack 312 | LDI PARAM, (1<