--- a/hw.S Wed May 05 17:33:30 2010 +0300
+++ b/hw.S Wed May 05 23:43:38 2010 +0300
@@ -20,8 +20,8 @@
; Setup Timer 0
; Count to 64k
- ldi r18, HIGH(0xffff)
- ldi r19, LOW(0xffff)
+ ldi r18, HIGH(0xffff/2)
+ ldi r19, LOW(0xffff/2)
sts OCR1AH, r18
sts OCR1AL, r19
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/led7seg.s Wed May 05 23:43:38 2010 +0300
@@ -0,0 +1,199 @@
+.nolist
+.include "m168def.inc" ; Same family as 328P
+.list
+
+;; Interrupt Vector
+.org 0x00
+ rjmp init
+
+.org SPIaddr
+ rjmp SPI_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_Send:
+ ; 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
+
+ ; Flag
+ cbi SPI_FLAGS, SPI_BUSY
+
+ ; Done
+ out SREG, r16
+ reti
+
+;; 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 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_DOT = 10
+.equ LCD_EMPTY = 11
+
+;; 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_Send
+ 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
+
+ ; Invert
+ com r16
+
+ ; Display
+ rcall SPI_Send
+
+ ; Done
+ ret
+
+init:
+ ; Stack
+ ldi r16, high(RAMEND)
+ ldi r17, low(RAMEND)
+ out SPH, r16
+ out SPL, r17
+
+ ; Enable interrupts
+ sei
+
+ ; SPI
+ rcall SPI_Init
+
+ ; LCD (requires interrupts)
+ rcall LCD_Init
+
+main:
+ ; Output something
+ ldi r16, LCD_4
+ rcall LCD_Show
+
+loop:
+ rjmp loop
+