matrix.inc
author Tero Marttila <terom@fixme.fi>
Thu, 17 Jun 2010 20:00:27 +0300
changeset 33 0d0309787be3
child 34 4646abd073fb
permissions -rw-r--r--
Working matrix scan
;; LED Matrix driver
;;

.set MATRIX_DDR = DDRB
.set MATRIX_PORT = PORTB
.set MATRIX_OE = PORTB1		; Output Enable, active low, externally pulled high

.dseg
.set MATRIX_COLS = 8		; number of columns

matrix_colbit:	.byte 1					; column bit
matrix_rowbuf:	.byte MATRIX_COLS		; row bitmask by column

.cseg

;; Normalize the outputs, enable the matrix, an set up buffers
Matrix_Init:
    ; Setup ENable port
        sbi         MATRIX_PORT, MATRIX_OE	; high -> disabled
        sbi         MATRIX_DDR, MATRIX_OE	; out
 
	; blank hardware
		ldi			r16, 0

		sts			spi_outbuf + 0, r16		; column sinks
		sts			spi_outbuf + 1, r16		; row drivers

	; write out
		rcall		SPI_SendRecv

	; enable
		cbi			MATRIX_PORT, MATRIX_OE	; low -> enabled

	; init buffers
		ldi			r16, 0b1
		sts			matrix_colbit, r16

		ldi			r16, 0
		ldi			r17, MATRIX_COLS
		ldi			YL, low(matrix_rowbuf)
		ldi			YH, high(matrix_rowbuf)

m_init_mzero:
		st			Y+, r16
		
		; loop until zero
		dec			r17
		brne		m_init_mzero

	; Use Timer0, 32k cycles -> 500Hz scan rate
		ldi			r16, 32
		rcall		Timer0_Start

	; done
		ret

;; Scan the next column
;;  Interrupt-driven
Matrix_ScanCol:
	; Column bit
		; load
		lds			r16, matrix_colbit
	
		; start packet
        cbi         SPI_PORT, SPI_SS

		; output
		out			SPDR, r16

	; Compute col index
		ldi			r17, 0

m_sc_colidx:
		; shift
		lsr			r16

		; done if we shifted the bit out
		brcs		m_sc_row

		; count shifts
		inc			r17
		rjmp		m_sc_colidx

m_sc_row:
	; Row mask
		; base
		ldi			XL, low(matrix_rowbuf)
		ldi			XH, high(matrix_rowbuf)

		; offset
		ldi			r18, 0

		add			XL, r17
		adc			XH, r18

		; load
		ld			r16, X

		; output
		rcall		SPI_Wait
		out			SPDR, r16

	; Update col bit
		lds			r16, matrix_colbit
	
		; shift left
		lsl			r16
		brcc		m_sc_colout

		; overflow, take bit from C
		rol			r16

m_sc_colout:
		; store
		sts			matrix_colbit, r16

	; End of packet
		rcall		SPI_Wait
        sbi         SPI_PORT, SPI_SS

	; Done
		ret

;; Scan the matrix once in one go
Matrix_ScanFull:
	; Row index
		ldi			ZL, low(matrix_rowbuf)
		ldi			ZH, high(matrix_rowbuf)

	; Column bit
		ldi			r25, 0
		sec								; set C
		
m_pulse_col:
		; rotate bit left from C
		rol			r25
		
		; overflow
		brcs		m_pulse_end
		
		; store in output buffer
		sts			spi_outbuf + 1, r25

	; Row mask
		ld			r16, Z+

		sts			spi_outbuf + 0, r16

	; Display
		rcall		SPI_SendRecv

	; Next column
		rjmp		m_pulse_col

m_pulse_end:
	; Done
		ret