; ; ******************************************** ; * LED-grave 8-by-8 LED matrix * ; * Version 1 as of January 2011 * ; * (C)2011 by http://avr-asm-tutorial.net * ; ******************************************** ; ; Include-file for ATmega16 .NOLIST .INCLUDE "m16def.inc" ; Header for mega16 .LIST ; ; ============================================ ; H A R D W A R E I N F O R M A T I O N S ; ============================================ ; ATmega16 ___________ ; 1 / |40 ; S1-P0 o--|PB0 PA0|--o Col1u ; S2-P1 o--|PB1 PA1|--o Col2u ; S3-uu o--|PB2 PA2|--o Col3u ; S4-XR o--|PB3 PA3|--o Col4u ; --|PB4 PA4|--o Col5u ; MOSI o--|MOSI PA5|--o Col6u ; MISO o--|MISO PA6|--o Col7u ; SCK o--|SCK PA7|--o Col8u ; RESET o--|RESET AREF|-- ; VCC o--|VCC |--o GND ; GND o--|GND AVCC|-- ; --|XTAL2 PC7|--o Col8l ; --|XTAL1 PC6|--o Col7l ; Row1u o--|PD0 PC5|--o Col6l ; Row2u o--|PD1 PC4|--o Col5l ; Row3u o--|PD2 PC3|--o Col4l ; Row4u o--|PD3 PC2|--o Col3l ; Row1l o--|PD4 PC1|--o Col2l ; Row2l o--|PD5 PC0|--o Col1l ; Row3l o--|PD6 PD7|--o Row4l ; |____________| ; ; Switches: ; --------- ; S1,S2 : selects text sequences 0..3 ; S3 on : exchanges characters ; off: rotates characters to the left ; S4 on : maximum display brightness ; off: half display brightness ; ; Fuses: ; ------ ; The following fuses must be selected: ; - JTAGEN fuse off (JTAG disabled) ; - EESAVE fuse on (save EEPROM content ; during flashing) ; The following clock fuses have to be ; selected (default value): ; - SUT CK SEL = Int RC Osc, 1 MHz, 6 CK + 64 ms ; Fuse setting: High=D1, Low=E1 ; ; ============================================ ; P O R T S A N D P I N S ; ============================================ ; .equ pColU = PORTA ; Upper Column driver .equ pColUD = DDRA ; Upper Column direction .equ pColL = PORTC ; Lower Column driver .equ pColLD = DDRC ; Lower Column direction .equ pRow = PORTD ; Row driver .equ pRowD = DDRD ; Row driver direction .equ pSw = PORTB ; Switch input port .equ pSwD = DDRB ; Switch input port direction ; ; ; ============================================ ; P R O G R A M I N F O ; ============================================ ; ; Processor clock: ; The processor runs with its default setting: ; internal RC clock generator with 1 MHz ; ; Timer 1: ; 16-bit-timer 1 is in CTC mode, using the ICR ; register for timer compare and clear. Inter- ; rupts are enabled on the ICR compare, muxing ; the display column. ; If display brightness has been selected low, ; the Compare Match Int on compare register A ; is additionally enabled. This Int switches ; the row drivers off at half of the CTC time. ; ; LED driving: ; Ports A and C drive the column transistors, ; port D drives the row transistors. ; Timer 1 int on ICR match ; - clears all row drivers, ; - outputs the column info in SRAM on ports A and C, ; - switches the row driver on again. ; The row byte (0x88, 0x44, 0x22,0x11) is then ; shifted right. If a carry shift out, four shifts ; have been made. The the row byte is restartet ; at 0x88 and the pointer X to the mux data in ; SRAM is restarted. ; If four shifts have been made a counter is ; decreased. If the counter reaches zero, the T flag ; is set and the counter is reloaded from register ; rAct. The T flag is cleared by the software outside ; the Int. ; Register rAct allows to dynamically select different ; display speeds. ; If S3 is off (shift in and out), the speed info ; in the text stream is divided by eight to allow a ; faster shifting. ; If S4 is off, the LEDs are switched off after half ; of the mux time (lower brightness). If S4 is on, ; the LEDs are on over the complete mux time. ; ; Text display: ; Four text sequences can be placed into the EEPROM, ; each ending with a 0xFF character. Character code ; is 7-bit-ASCII, the lower 32 characters are graphic ; characters. ; Within the text stream speed information can be ; placed using codes between 128 and 254, setting ; the speed (128=256 mux cycles, 129=1 mux cycle, ; 130=2 mux cycles, etc.). ; Depending from the switches S1 and S2 one of the ; four text sequences in the EEPROM is selected and ; displayed. ; If S3 is on, the text is displayed character by ; character. If S3 is off the display shifts left and ; the next character is shifted in from the right side. ; ; ================================================ ; C O N S T A N T S T O C H A N G E ; ================================================ ; .equ mux_freq = 50 ; MUX frequency of the display ; ; ======================================================= ; F I X E D A N D D E R I V E D C O N S T A N T S ; ======================================================= ; .equ clock = 1000000 ; Internal default RC clock frequency .equ mux_int_freq = 4 * mux_freq ; interrupt frequency for MUX .equ presc = 8 ; 16-bit timer prescaler .equ comp = clock / presc / mux_int_freq ; 16-bit timer compare ; ; ============================================ ; R E G I S T E R D E F I N I T I O N S ; ============================================ ; ; used: R0 for LPM and other purposes outside ints, unnamed ; used: R1..R8 for shifting purposes outside ints, unnamed ; free: R9..R14 .def rSreg = R15 ; temporary SREG flag register .def rmp = R16 ; multi purpose register outside ints .def rimp = R17 ; multi purpose register inside ints .def rCntDwn = R18 ; count down register .def rMux = R19 ; mux row driver register .def rAct = R20 ; number of mux cycles for T setting .def rChr = R21 ; counter for rotating characters .def rLCol = R22 ; column or register for last column ; free: R23..R25 ; used: R27:R26 (X) as pointer to mux data, inside ints ; used: R29:R28 (Y) for pointing purposes outside ints ; used: R31:R30 (Z) for pointing purposes outside ints ; ; ============================================ ; S R A M D E F I N I T I O N S ; ============================================ ; .DSEG .ORG Sram_Start MuxData: ; Display info for MUXing LEDs .byte 8 ; ; ============================================== ; R E S E T A N D I N T V E K T O R S ; ============================================== ; .CSEG .ORG $0000 rjmp Main ; Reset-Vektor nop reti ; Int0 nop reti ; Int1 nop reti ; TC2 compare int nop reti ; TC2 overflow nop rjmp Tc1Capt ; TC1 capture int nop rjmp Tc1CmpA ; TC1 compare A nop reti ; TC1 compare B nop reti ; TC1 overflow nop reti ; TC0 overflow nop reti ; SPI STC nop reti ; USART RXC nop reti ; USART UDRE nop reti ; USART TXC nop reti ; ADC nop reti ; EE_RDY nop reti ; ANA_COMP nop reti ; TWI nop reti ; INT2 nop reti ; TC0 Compare nop reti ; SPM Ready nop ; ; ; ========================================== ; I N T E R R U P T S E R V I C E S ; ========================================== ; ; MUX interrupt service routine Tc1Capt: in rSreg,SREG ldi rimp,0 ; clear display out pRow,rimp ld rimp,X+ ; read upper column value out pColU,rimp ; write upper column driver ld rimp,X+ ; read lower column value out pColL,rimp ; write lower column driver out pRow,rMux ; activate display lsr rMux ; shift mux register right brcc Tc1Capt1 ; no carry, continue ldi rMux,0x88 ; start with first column ldi XL,LOW(MuxData) ; set pointer to first dec rCntDwn ; count down brne Tc1Capt1 ; not zero, go on mov rCntDwn,rAct ; restart counter out SREG,rSreg ; restore SREG set ; set T flag reti Tc1Capt1: out SREG,rSreg ; restore SREG reti ; ; Tc1CmpA switches the display off Tc1CmpA: ldi rimp,0 ; write 0 to row drivers out pRow,rimp reti ; ; ============================================ ; M A I N P R O G R A M I N I T ; ============================================ ; Main: ; Init stack ldi rmp,HIGH(RAMEND) ; stack pointer to RAMEND out SPH,rmp ldi rmp,LOW(RAMEND) out SPL,rmp ; Init Mux variables ldi rMux,0x88 ; start with highest rows, shift right ldi rAct,50 ; mux cycles for T-setting, 1 second mov rCntDwn,rAct ; mux cycle counter in ints ldi XH,HIGH(MuxData) ; point X to MuxData in SRAM ldi XL,LOW(MuxData) ; Init display ports clr rmp ; all display ports off out pColU,rmp ; upper columns out pColL,rmp ; lower columns out pRow,rmp ; rows ldi rmp,0xFF ; all port drivers of display to output out pColUD,rmp ; upper column driver out pColLD,rmp ; lower column driver out pRowD,rmp ; row driver ; Init display test ldi YH,HIGH(MuxData) ; point Y to mux in SRAM ldi YL,LOW(MuxData) ldi rmp,'A' ; Display character A on startup rcall Rmp2Asc ldi rmp,8 WriteDisp: lpm R0,Z+ st Y+,R0 dec rmp brne WriteDisp ; Init Switch ports clr rmp ; switch port direction to input out pSwD,rmp ldi rmp,0x0F ; pull-up resistor of switches to on out pSw,rmp ; Init TC1 as mux timer with ICR-CTC and Compare A int ldi ZH,HIGH(comp) ; TC1 CTC value to ICR ldi ZL,LOW(comp) out ICR1H,ZH out ICR1L,ZL lsr ZH ; TC1 compare A to half time ror ZL out OCR1AH,ZH ; TC1 compare A value out OCR1AL,ZL ldi rmp,0 ; WGM11 and WGM10 to zero out TCCR1A,rmp ldi rmp,(1<' .db 24,12,60,24,102,0,4,24 ; '?' .db 124,168,130,185,132,130,184,124 ; '@' .db 24,195,60,255,102,255,195,195 ; 'A' .db 252,254,254,195,195,254,254,252 ; 'B' .db 60,192,126,195,195,126,192,60 ; 'C' .db 252,195,254,195,195,254,195,252 ; 'D' .db 255,248,255,192,192,255,248,255 ; 'E' .db 255,248,254,240,192,192,192,192 ; 'F' .db 60,255,126,227,195,126,192,60 ; 'G' .db 195,255,195,195,195,195,255,195 ; 'H' .db 60,24,24,24,24,24,24,60 ; 'I' .db 255,3,255,198,3,252,3,120 ; 'J' .db 198,240,204,216,216,204,240,198 ; 'K' .db 192,192,192,192,192,254,192,254 ; 'L' .db 195,219,231,195,255,195,219,195 ; 'M' .db 195,219,227,207,243,199,219,195 ; 'N' .db 24,195,60,102,102,60,195,24 ; 'O' .db 252,252,254,192,195,192,254,192 ; 'P' .db 24,203,60,102,102,62,195,27 ; 'Q' .db 252,254,254,204,195,198,254,195 ; 'R' .db 60,126,126,3,195,254,224,124 ; 'S' .db 255,24,255,24,24,24,24,24 ; 'T' .db 195,195,195,195,195,126,195,60 ; 'U' .db 195,195,195,102,195,60,195,24 ; 'V' .db 195,219,195,219,195,231,219,102 ; 'W' .db 195,60,195,102,102,195,60,195 ; 'X' .db 195,60,195,24,195,24,102,24 ; 'Y' .db 255,24,255,49,134,127,12,254 ; 'Z' .db 56,32,32,32,32,32,32,56 ; '[' .db 48,4,16,4,8,2,8,2 ; '\' .db 28,4,4,4,4,4,4,28 ; ']' .db 8,0,20,0,34,0,0,0 ; '^' .db 0,0,0,0,0,0,0,255 ; '_' .db 6,0,12,0,24,0,0,0 ; '´' .db 0,38,0,98,0,38,26,26 ; ' a' .db 32,50,32,35,32,50,44,44 ; ' b' .db 0,102,0,64,0,102,60,60 ; ' c' .db 4,124,4,132,4,124,52,52 ; ' d' .db 0,50,0,100,0,41,30,30 ; ' e' .db 14,30,26,16,16,16,16,16 ; ' f' .db 0,68,0,60,0,4,56,120 ; ' g' .db 32,56,32,36,32,36,32,36 ; ' h' .db 0,16,0,16,16,16,0,16 ; ' i' .db 0,8,8,8,0,40,8,16 ; ' j' .db 32,40,32,48,32,40,38,38 ; ' k' .db 32,32,32,32,32,18,32,12 ; ' l' .db 0,180,0,218,0,146,0,146 ; ' m' .db 0,44,0,50,0,34,0,34 ; ' n' .db 0,24,0,36,0,36,0,24 ; ' o' .db 0,26,0,26,0,20,20,16 ; ' p' .db 0,76,0,76,0,52,52,4 ; ' q' .db 0,50,0,32,0,32,44,32 ; ' r' .db 0,48,0,8,24,36,36,24 ; ' s' .db 32,32,32,32,32,18,120,12 ; ' t' .db 0,34,0,34,0,38,34,26 ; ' u' .db 0,34,0,20,0,20,34,8 ; ' v' .db 0,129,0,90,0,90,129,36 ; ' w' .db 0,40,0,16,0,40,68,68 ; ' x' .db 0,36,0,28,0,4,36,4 ; ' y' .db 0,8,0,16,0,36,124,124 ; ' z' .db 12,48,8,8,8,8,48,12 ; '0' .db 8,8,8,8,8,8,8,8 ; '|' .db 24,6,8,8,8,8,6,24 ; '}' .db 0,74,0,132,0,0,49,0 ; '~' ; ; ============================================ ; D I S P L A Y T E X T E E P R O M ; ============================================ ; .eseg ; Start of EEPROM segment ; bytes 128..254: set speed to (value-128), ; if rotate-in is selected: (value-128) / 8 ; byte 0xFF to stop and restart sequence .org $0000 ; Text0: .db 4+0x80,' ',0,1,2,3,2,1,0 ; explode and implode .db 16+0x80,4,5,6,5,4,0,' ' ; cross .db 4+0x80,7,8,9,10,11,12,13,14,7,' ' ; rotate .db 16+0x80,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30 ; spiral .db 32+0x80,29,28,27,26,25,24,23,22,21,20,19,18,17,16,' ' ; spiral back .db 0xFF Text1: .db 32+0x80,"Gerhard Schmidt, Kastanienallee 20, 64289 Darmstadt",0xFF Text2: .db 40+0x80,"Welcome to LED grave by DG4FAC, version 1 ",0xFF Text3: .db 64+0x80,"Text unprogrammed ",0xFF ; ; End of EEPROM segment .cseg ; ; End of source code ; Copyright info .db "(C)2010 by Gerhard Schmidt " ; menschenlesbar .db "C(2)10 0ybG reahdrS hcimtd " ; wortgerecht ;