# HG changeset patch # User Tero Marttila # Date 1273323618 -10800 # Node ID a7c668003a19758025c78439dd5bdf5a6029c542 # Parent 11d6167a67cb9322334e14eb5bc63d89b6cddba5 split led7seg.s into .inc modules, and update Makefile to use .s -> .hex, and above .inc's for led7seg diff -r 11d6167a67cb -r a7c668003a19 Makefile --- a/Makefile Sat May 08 15:13:45 2010 +0300 +++ b/Makefile Sat May 08 16:00:18 2010 +0300 @@ -4,20 +4,23 @@ AD_PART = m328p AD_PROG = arduino AD_BAUD = 57600 -AD_PORT = /dev/ttyUSB1 +AD_PORT = /dev/ttyUSB0 AD = avrdude ADFLAGS = -p $(AD_PART) -c $(AD_PROG) -b $(AD_BAUD) -P $(AD_PORT) -PROG = console - -all: $(PROG).s.hex +PROG = led7seg -%.s.hex: %.s +led7seg.hex: spi.inc led7seg.inc adc.inc delay.inc + +all: $(PROG).hex + +%.hex: %.s $(AS) $(ASFLAGS) $< + mv $<.hex $@ -upload: $(PROG).s.hex - $(AD) $(ADFLAGS) -U flash:w:$(PROG).s.hex +upload: $(PROG).hex + $(AD) $(ADFLAGS) -U flash:w:$< SERIAL_BAUD = 9600 SERIAL_FLOW = n diff -r 11d6167a67cb -r a7c668003a19 adc.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/adc.inc Sat May 08 16:00:18 2010 +0300 @@ -0,0 +1,55 @@ +.equ ADC_DDR = DDRC +.equ ADC_PORT = PORTC +.equ ADC_PIN = PORTC0 + +;; Initialize the ADC for starting conversions +ADC_Init: + ; Setup ADMUX + ; Use AVcc as ref + ; Left-adjust result (for 8-bit access) + ; Select ADC0 + ldi r16, (0b01 << REFS0) | (1 << ADLAR) | (0b000 << MUX0) + sts ADMUX, r16 + + ; Setup ADCSRB + ; Free-running mode + ldi r16, (0b000 << ADTS0) + sts ADCSRB, r16 + + ; Setup ADCSRA + ; Enable + ; Start right away... + ; Auto-trigger + ; Enable Interrupt + ; Scale 1/128 + ldi r16, (1 << ADEN) | (1 << ADSC) | (1 << ADATE) | (1 << ADIE) | (0b111 << ADPS0) + sts ADCSRA, r16 + + ; Disable digital circuit for pin + ldi r16, (1 << ADC_PIN) + sts DIDR0, r16 + + ; Debug LED + sbi DDRD, PORTD7 + sbi PORTD, PORTD7 + + ; Done + ret + +ADC_Interrupt: + ; Off + cbi PORTD, PORTD7 + + ; Done + reti + +;; Read the current 8-bit ADC sample +; Returns value in r16 +ADC_Read8: + ; Copy + lds r16, ADCH + + ; Done + ret + + diff -r 11d6167a67cb -r a7c668003a19 delay.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/delay.inc Sat May 08 16:00:18 2010 +0300 @@ -0,0 +1,36 @@ +;; +;; Busy-loop delays +;; + +;; Delay for approx. one second +Delay_1s: + ; ~16M cycles + ldi r20, 82 + rjmp delay_init + +;; Delay for a variable amount of time, adjusted by r20 +; Input: r20 controls number of delay loops +VarDelay: + tst r20 + breq delay_out + +delay_init: + ldi r21, 255 + +delay_loop: + ; 254 * (1 + 2) + 1 * (1 + 1) = 764 cycles / loop + dec r22 + brne delay_loop + + ; 254 * 764 + 764 = 194820 cycles / loop + dec r21 ; 1 * r20 * r21 + brne delay_loop ; 2 * r20 * r21 + + ; r20 * 194820 + r20 * 3 = 194823 cycles / loop (r20) + dec r20 ; 1 * r20 + brne delay_loop ; 2 * r20 + +delay_out: + ret + + diff -r 11d6167a67cb -r a7c668003a19 led7seg.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/led7seg.inc Sat May 08 16:00:18 2010 +0300 @@ -0,0 +1,96 @@ +.equ LED7_DDR = DDRB +.equ LED7_PORT = PORTB +.equ LED7_OE = PORTB1 ; Output Enable (Low) + +; Output font for 7-segment display +LED7_Font: +.db 0b00111111, 0b00000110 ; 0, 1 +.db 0b01011011, 0b01001111 ; 2, 3 +.db 0b01100110, 0b01101101 ; 4, 5 +.db 0b01111101, 0b00000111 ; 6, 7 +.db 0b01111111, 0b01100111 ; 8, 9 +.db 0b01110111, 0b01111100 ; A, b +.db 0b00111001, 0b01011110 ; C, d +.db 0b01111001, 0b01110001 ; E, f +.db 0b10000000, 0b00000000 ; ., + +;.db 0b00111111, ; 0 +; 0b00000110, ; 1 +; 0b01011011, ; 2 +; 0b01001111, ; 3 +; 0b01100110, ; 4 +; 0b01101101, ; 5 +; 0b01111101, ; 6 +; 0b00000111, ; 7 +; 0b01111111, ; 8 +; 0b01100111, ; 9 +; 0b10000000, ; . +; 0b01000000 ; + +.equ LED7_0 = 0 +.equ LED7_1 = 1 +.equ LED7_2 = 2 +.equ LED7_3 = 3 +.equ LED7_4 = 4 +.equ LED7_5 = 5 +.equ LED7_6 = 6 +.equ LED7_7 = 7 +.equ LED7_8 = 8 +.equ LED7_9 = 9 +.equ LED7_A = 10 +.equ LED7_B = 11 +.equ LED7_C = 12 +.equ LED7_D = 13 +.equ LED7_E = 14 +.equ LED7_F = 15 +.equ LED7_DOT = 16 +.equ LED7_EMPTY = 17 + +;; Initialize LCD to empty, and enable +LED7_Init: + ; Setup ENable port + sbi LED7_PORT, LED7_OE ; Disabled (Low) + sbi LED7_DDR, LED7_OE ; Out + + ; empty + ldi r16, 0b11111111 + + ; Output + rcall SPI_SendRecv + rcall SPI_Wait + + ; Enable + cbi LED7_PORT, LED7_OE + + ; Done + ret + +;; Display a single digit on the display +;; Input: r16 +LED7_Show: + clr r0, 0 + + ; Prep address + ; base addr for font table + ldi ZH, high(2*LED7_Font) + ldi ZL, low(2*LED7_Font) + + ; offset + add ZL, r16 + adc ZH, r0 + + ; Load char + lpm r16, Z + + ;; Continue + +;; Display a raw segment mask +;; Input: r16 +LED7_ShowRaw: + ; Invert + ; com r16 + + ; Display + rjmp SPI_SendRecv + + diff -r 11d6167a67cb -r a7c668003a19 led7seg.s --- a/led7seg.s Sat May 08 15:13:45 2010 +0300 +++ b/led7seg.s Sat May 08 16:00:18 2010 +0300 @@ -13,272 +13,27 @@ rjmp ADC_Interrupt ;; SPI -.equ SPI_DDR = DDRB -.equ SPI_PORT = PORTB -.equ SPI_SCK = PORTB5 -.equ SPI_MISO = PORTB4 -.equ SPI_MOSI = PORTB3 -.equ SPI_SS = PORTB2 - -.equ SPI_FLAGS = GPIOR0 -.equ SPI_BUSY = 0 - -;; Initialize SPI subsystem for master operation -SPI_Init: - ; Set modes - sbi SPI_DDR, SPI_SCK ; Out - sbi SPI_DDR, SPI_MOSI ; Out - sbi SPI_DDR, SPI_SS ; Out - - ; Drive SS high (off) - sbi SPI_PORT, SPI_SS - - ; Set control mode - ; Enable interrupt - ; Enable SPI - ; MSB first - ; Master mode - ; Polarity/phase: Mode 0 (sample on rising edge) - ; Clock rate 1/16 - ldi r16, (1 << SPIE) | (1 << SPE) | (0 << DORD) | (1 << MSTR) | (0 << CPOL) | (0 << CPHA) | (0b01 << SPR0) - out SPCR, r16 - - ; Flags - clr r0 - out SPI_FLAGS, r0 - - ; Done - ret - -;; Send byte -;; Input: r16 -;; XXX: should not be busy... -SPI_SendRecv: - ; Flag - sbi SPI_FLAGS, SPI_BUSY - - ; Enable slave (low) - cbi SPI_PORT, SPI_SS - - ; Write byte (starts SCK) - out SPDR, r16 - - ; Wait for interrupt - ; Done - ret - -;; Wait for byte to be sent -SPI_Wait: -wait_idle: - sbic SPI_FLAGS, SPI_BUSY ; Test for busy flag - rjmp wait_idle ; loop - - ; Done - ret - -;; Service SPI interrupt -SPI_Interrupt: - ; Store SREG - in r16, SREG - - ; Drive SS high (off) - sbi SPI_PORT, SPI_SS - - ; Read - in r10, SPDR - - ; Flag - cbi SPI_FLAGS, SPI_BUSY - - ; Done - out SREG, r16 - reti +.include "spi.inc" ;; LCD -.equ LCD_DDR = DDRB -.equ LCD_PORT = PORTB -.equ LCD_OE = PORTB1 ; Output Enable (Low) - -; Output font for 7-segment display -LCD_Font: -.db 0b00111111, 0b00000110 ; 0, 1 -.db 0b01011011, 0b01001111 ; 2, 3 -.db 0b01100110, 0b01101101 ; 4, 5 -.db 0b01111101, 0b00000111 ; 6, 7 -.db 0b01111111, 0b01100111 ; 8, 9 -.db 0b01110111, 0b01111100 ; A, b -.db 0b00111001, 0b01011110 ; C, d -.db 0b01111001, 0b01110001 ; E, f -.db 0b10000000, 0b00000000 ; ., - -;.db 0b00111111, ; 0 -; 0b00000110, ; 1 -; 0b01011011, ; 2 -; 0b01001111, ; 3 -; 0b01100110, ; 4 -; 0b01101101, ; 5 -; 0b01111101, ; 6 -; 0b00000111, ; 7 -; 0b01111111, ; 8 -; 0b01100111, ; 9 -; 0b10000000, ; . -; 0b01000000 ; - -.equ LCD_0 = 0 -.equ LCD_1 = 1 -.equ LCD_2 = 2 -.equ LCD_3 = 3 -.equ LCD_4 = 4 -.equ LCD_5 = 5 -.equ LCD_6 = 6 -.equ LCD_7 = 7 -.equ LCD_8 = 8 -.equ LCD_9 = 9 -.equ LCD_A = 10 -.equ LCD_B = 11 -.equ LCD_C = 12 -.equ LCD_D = 13 -.equ LCD_E = 14 -.equ LCD_F = 15 -.equ LCD_DOT = 16 -.equ LCD_EMPTY = 17 - -;; Initialize LCD to empty, and enable -LCD_Init: - ; Setup ENable port - sbi LCD_PORT, LCD_OE ; Disabled (Low) - sbi LCD_DDR, LCD_OE ; Out - - ; empty - ldi r16, 0b11111111 - - ; Output - rcall SPI_SendRecv - rcall SPI_Wait - - ; Enable - cbi LCD_PORT, LCD_OE - - ; Done - ret - -;; Display a single digit on the display -;; Input: r16 -LCD_Show: - clr r0, 0 - - ; Prep address - ; base addr for font table - ldi ZH, high(2*LCD_Font) - ldi ZL, low(2*LCD_Font) - - ; offset - add ZL, r16 - adc ZH, r0 - - ; Load char - lpm r16, Z - - ;; Continue - -;; Display a raw segment mask -;; Input: r16 -LCD_ShowRaw: - ; Invert - ; com r16 - - ; Display - rjmp SPI_SendRecv +.include "led7seg.inc" ;; ADC -.equ ADC_DDR = DDRC -.equ ADC_PORT = PORTC -.equ ADC_PIN = PORTC0 - -;; Initialize the ADC for starting conversions -ADC_Init: - ; Setup ADMUX - ; Use AVcc as ref - ; Left-adjust result (for 8-bit access) - ; Select ADC0 - ldi r16, (0b01 << REFS0) | (1 << ADLAR) | (0b000 << MUX0) - sts ADMUX, r16 - - ; Setup ADCSRB - ; Free-running mode - ldi r16, (0b000 << ADTS0) - sts ADCSRB, r16 - - ; Setup ADCSRA - ; Enable - ; Start right away... - ; Auto-trigger - ; Enable Interrupt - ; Scale 1/128 - ldi r16, (1 << ADEN) | (1 << ADSC) | (1 << ADATE) | (1 << ADIE) | (0b111 << ADPS0) - sts ADCSRA, r16 - - ; Disable digital circuit for pin - ldi r16, (1 << ADC_PIN) - sts DIDR0, r16 - - ; Debug LED - sbi DDRD, PORTD7 - sbi PORTD, PORTD7 - - ; Done - ret +.include "adc.inc" -ADC_Interrupt: - ; Off - cbi PORTD, PORTD7 - - ; Done - reti - -;; Read the current 8-bit ADC sample -; Returns value in r16 -ADC_Read8: - ; Copy - lds r16, ADCH - - ; Done - ret - -;; Delay for approx. one second -Delay_1s: - ; 40 * 64k = 2.6M loops - ldi r20, 40 - -;; Delay for r20 * 64k cycles -VarDelay: - ldi r21, 255 - -;; Delay for r20 * r21 * 255 cycles -ShortDelay: - ldi r22, 255 - -delay: - dec r22 - brne delay - dec r21 - brne delay - dec r20 - brne delay - - ret - +;; Utils +.include "delay.inc" ;; Count down from 9 ; Returns once we've hit zero Main_Countdown: ; init from F - ldi r24, LCD_F + ldi r24, LED7_F _count_loop: ; display mov r16, r24 - rcall LCD_Show + rcall LED7_Show ; exit if zero tst r24 @@ -301,15 +56,15 @@ Main_Blink: _blink_loop: ; dot - ldi r16, LCD_DOT - rcall LCD_Show + ldi r16, LED7_DOT + rcall LED7_Show ; wait... rcall Delay_1s ; empty - ldi r16, LCD_EMPTY - rcall LCD_Show + ldi r16, LED7_EMPTY + rcall LED7_Show rcall Delay_1s @@ -325,9 +80,9 @@ _spin_next: ; display mov r16, r24 - rcall LCD_ShowRaw + rcall LED7_ShowRaw - ; variable delay -> r16 + ; delay from ADC ;rcall ADC_Read8 ;mov r20, r16 @@ -337,9 +92,8 @@ ; constant ;ldi r20, 20 - ; short delay, from ADC - ldi r21, 255 - rcall ShortDelay + ; short delay + rcall VarDelay ; next segment lsl r24 @@ -368,15 +122,15 @@ rcall SPI_Init ; LCD (requires interrupts, blocks) - rcall LCD_Init + rcall LED7_Init ; Run ; spin! - ;rcall Main_Spin + rcall Main_Spin ; count! - rcall Main_Countdown - rcall Main_Blink + ; rcall Main_Countdown + ; rcall Main_Blink end: rjmp end diff -r 11d6167a67cb -r a7c668003a19 spi.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/spi.inc Sat May 08 16:00:18 2010 +0300 @@ -0,0 +1,84 @@ +;; vim: filetype=avr + +;; SPI +.equ SPI_DDR = DDRB +.equ SPI_PORT = PORTB +.equ SPI_SCK = PORTB5 +.equ SPI_MISO = PORTB4 +.equ SPI_MOSI = PORTB3 +.equ SPI_SS = PORTB2 + +.equ SPI_FLAGS = GPIOR0 +.equ SPI_BUSY = 0 + +;; Initialize SPI subsystem for master operation +SPI_Init: + ; Set modes + sbi SPI_DDR, SPI_SCK ; Out + sbi SPI_DDR, SPI_MOSI ; Out + sbi SPI_DDR, SPI_SS ; Out + + ; Drive SS high (off) + sbi SPI_PORT, SPI_SS + + ; Set control mode + ; Enable interrupt + ; Enable SPI + ; MSB first + ; Master mode + ; Polarity/phase: Mode 0 (sample on rising edge) + ; Clock rate 1/16 + ldi r16, (1 << SPIE) | (1 << SPE) | (0 << DORD) | (1 << MSTR) | (0 << CPOL) | (0 << CPHA) | (0b01 << SPR0) + out SPCR, r16 + + ; Flags + clr r0 + out SPI_FLAGS, r0 + + ; Done + ret + +;; Send byte +;; Input: r16 +;; XXX: should not be busy... +SPI_SendRecv: + ; Flag + sbi SPI_FLAGS, SPI_BUSY + + ; Enable slave (low) + cbi SPI_PORT, SPI_SS + + ; Write byte (starts SCK) + out SPDR, r16 + + ; Wait for interrupt + ; Done + ret + +;; Wait for byte to be sent +SPI_Wait: + sbic SPI_FLAGS, SPI_BUSY ; Test for busy flag + rjmp SPI_Wait ; loop + + ; Done + ret + +;; Service SPI interrupt +SPI_Interrupt: + ; Store SREG + in r16, SREG + + ; Drive SS high (off) + sbi SPI_PORT, SPI_SS + + ; Read + in r10, SPDR + + ; Flag + cbi SPI_FLAGS, SPI_BUSY + + ; Done + out SREG, r16 + reti + +