terom@18: ;; terom@18: ;; Driving 7-segment LED displays over SPI terom@18: ;; terom@18: terom@18: ; Output Enable control terom@17: .equ LED7_DDR = DDRB terom@17: .equ LED7_PORT = PORTB terom@17: .equ LED7_OE = PORTB1 ; Output Enable (Low) terom@17: terom@18: ; Font for 7-segment display terom@18: ; Includes decimal digits 0-9, hexadecimal digits A-F, and some special chars terom@17: LED7_Font: terom@17: .db 0b00111111, 0b00000110 ; 0, 1 terom@17: .db 0b01011011, 0b01001111 ; 2, 3 terom@17: .db 0b01100110, 0b01101101 ; 4, 5 terom@17: .db 0b01111101, 0b00000111 ; 6, 7 terom@17: .db 0b01111111, 0b01100111 ; 8, 9 terom@17: .db 0b01110111, 0b01111100 ; A, b terom@17: .db 0b00111001, 0b01011110 ; C, d terom@17: .db 0b01111001, 0b01110001 ; E, f terom@17: .db 0b10000000, 0b00000000 ; ., terom@17: terom@23: .equ LED7_0 = 0 terom@23: .equ LED7_1 = 1 terom@23: .equ LED7_2 = 2 terom@23: .equ LED7_3 = 3 terom@23: .equ LED7_4 = 4 terom@23: .equ LED7_5 = 5 terom@23: .equ LED7_6 = 6 terom@23: .equ LED7_7 = 7 terom@23: .equ LED7_8 = 8 terom@23: .equ LED7_9 = 9 terom@23: .equ LED7_A = 10 terom@23: .equ LED7_B = 11 terom@23: .equ LED7_C = 12 terom@23: .equ LED7_D = 13 terom@23: .equ LED7_E = 14 terom@23: .equ LED7_F = 15 terom@23: .equ LED7_DOT = 16 terom@23: .equ LED7_EMPTY = 17 terom@17: terom@26: ; LEDs are on beginning of SPI universe terom@26: .set led7_buffer = spi_outbuf + 0 terom@17: terom@17: ;; Initialize LCD to empty, and enable terom@17: LED7_Init: terom@17: ; Setup ENable port terom@17: sbi LED7_PORT, LED7_OE ; Disabled (Low) terom@17: sbi LED7_DDR, LED7_OE ; Out terom@23: terom@23: ; Initialize buffer terom@30: ldi r16, 0b01000000 terom@23: sts led7_buffer + 0, r16 terom@23: sts led7_buffer + 1, r16 terom@17: terom@26: ; Update display terom@26: rcall SPI_SendRecv terom@17: terom@23: ; Enable output once the initial display has been shifted out terom@17: cbi LED7_PORT, LED7_OE terom@17: terom@17: ; Done terom@17: ret terom@17: terom@23: LED7_LoadChar: terom@17: clr r0, 0 terom@17: terom@17: ; Prep address terom@17: ; base addr for font table terom@23: ldi ZH, high(2 * LED7_Font) terom@23: ldi ZL, low(2 * LED7_Font) terom@17: terom@17: ; offset terom@23: add ZL, r8 terom@17: adc ZH, r0 terom@17: terom@17: ; Load char terom@23: lpm r8, Z terom@23: terom@23: ; Done terom@23: ret terom@25: terom@25: ;; Display an 8-bit hexadecimal value on the display terom@25: ;; Input: r16 terom@25: LED7_ShowHex: terom@25: ; base16 terom@25: ldi r17, 16 terom@25: terom@25: ; 1's terom@25: call div8u terom@25: terom@25: ; r16 = result, r15 = remainder terom@25: mov r17, r15 terom@25: terom@25: ; Continue terom@25: rjmp LED7_Show terom@25: terom@25: ;; Display an 8-bit decimal value on the display terom@25: ;; Input: r16 terom@25: LED7_ShowDec: terom@25: ; base10 terom@25: ldi r17, 10 terom@25: terom@25: ; 1's terom@25: call div8u terom@25: mov r8, r15 terom@25: terom@25: ; 10's terom@25: call div8u terom@25: mov r9, r16 ; 100's terom@25: terom@25: ; 1's from r8 terom@25: rcall LED7_LoadChar terom@25: mov r17, r8 terom@25: terom@25: ; 10's from r15 terom@25: mov r8, r15 terom@25: rcall LED7_LoadChar terom@25: mov r16, r8 terom@25: terom@25: ; Set dots for 100's terom@25: sbrc r9, 0 terom@25: ori r17, 0b10000000 ; +100 terom@25: sbrc r9, 1 terom@25: ori r16, 0b10000000 ; +200 terom@25: terom@25: ; Continue terom@25: rjmp LED7_ShowRaw terom@25: terom@23: ;; Display a single digit on the display terom@23: ;; Input: r16, r17 terom@23: LED7_Show: terom@23: mov r8, r16 terom@23: rcall LED7_LoadChar terom@23: mov r16, r8 terom@23: terom@25: mov r8, r17 terom@23: rcall LED7_LoadChar terom@25: mov r17, r8 terom@23: terom@17: ;; Continue terom@17: terom@17: ;; Display a raw segment mask terom@23: ;; Input: r16, r17 terom@17: LED7_ShowRaw: terom@26: ; Store buffer terom@23: sts led7_buffer + 0, r16 terom@23: sts led7_buffer + 1, r17 terom@23: terom@26: ; Update display terom@30: rjmp SPI_Update terom@17: