split led7seg.s into .inc modules, and update Makefile to use .s -> .hex, and above .inc's for led7seg
--- 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
--- /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
+
+
--- /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
+
+
--- /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
+
+
--- 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
--- /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
+
+