; ; ******************************************** ; * LED-Grab 8-mal-8 LED matrix * ; * Version 1 Januar 2011 * ; * (C)2011 by http://avr-asm-tutorial.net * ; ******************************************** ; ; Include-Datei fuer ATmega16 .NOLIST .INCLUDE "m16def.inc" ; Header fuer mega16 .LIST ; ; ============================================= ; H A R D W A R E I N F O R M A T I O N E N ; ============================================= ; 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 : Auswahl der Textsequenzen 0..3 ; S3 on : Ueberschreiben der Buchstaben im Display ; off: Rotieren des Textes im Display ; S4 on : Maximale Display Helligkeit ; off: Halbe Display Helligkeit ; ; Fuses: ; ------ ; Die folgenden Fuses muessen ausgewaehlt sein: ; - JTAGEN Fuse aus (JTAG disabled) ; - EESAVE Fuse an (beibehalten des EEPROM-Inhalts ; beim flashen) ; Die folgenden Fuses zur Takteinstellung sind ; auszuwaehlen (entspreicht dem Urzustand): ; - SUT CK SEL = Int RC Osc, 1 MHz, 6 CK + 64 ms ; Fuse Setting: High=D1, Low=E1 ; ; ============================================ ; P O R T S U N D P I N S ; ============================================ ; .equ pColU = PORTA ; Oberer Spaltentreiber .equ pColUD = DDRA ; Richtung oberer Spaltentreiber .equ pColL = PORTC ; Unterer Spaltentreiber .equ pColLD = DDRC ; Richtung unterer Spaltentreiber .equ pRow = PORTD ; Zeilentreiber .equ pRowD = DDRD ; Richtung Zeilentreiber .equ pSw = PORTB ; Schaltereingang .equ pSwD = DDRB ; Richtung Schaltereingang ; ; ; ============================================ ; P R O G R A M M I N F O ; ============================================ ; ; Prozessortakt: ; Der Prozessor laeuft mit seiner Defaulteinstellung, ; dem internen RC Taktgenerator mit 1 MHz ; ; Timer 1: ; 16-bit-Timer 1 wird im CTC-Mode betrieben und ; verwendet das ICR-Register fuer Vergleich und ; Ruecksetzen. Interrupts bei ICR-Compare-Match ; sind eingeschaltet und steuern das Multiplexen ; der Anzeige. In der programmierten Einstellung ; wird der Int alle 5 ms ausgefuehrt (50 Hz, 4 ; Zeilen). ; Falls mit dem Schalter 4 die niedrigere Hellig- ; keit ausgewaehlt ist, ist der Compare Match Int ; A zusaetzlich aktiv. Er schaltet die Zeilentrei- ; ber nach der halben Zeit (2,5 ms) aus. ; ; LED-Steuerung: ; Die Ports A und C treiben die Spaltentransistoren, ; Port D treibt die Zeilentransistoren. ; Der Timer 1 ICR Int ; - loescht alle Zeilentreiber, ; - gibt die Spaltendaten im SRAM an die Ports A ; und C aus, ; - schaltet dann die Zeilentransistoren an. ; Das Zeilenbyte (0x88, 0x44, 0x22,0x11) wird dann ; nach rechts geschoben. Wenn dabei ein Ueberlauf ; in das Carry-Flag erfolgt, sind vier Multiplex- ; zyklen vorbei. Das Zeilenbyte beginnt dann mit ; 0x88 neu und der Zeiger X auf die Spaltendaten ; im SRAM wird von vorne gestartet. ; Nach vier Schiebevorgaengen wird ein Zaehler ; vermindert. Erreicht dieser Null, dann wird das ; T-Flag gesetzt und der Zaehler aus dem Register ; rAct neu gesetzt. Das T-Flag wird von der Software ; auszerhalb des Interrupts rueckgesetzt. ; Das Register rAct erlaubt eine dynamische Einstel- ; der Display-Wechselgeschwindigkeit. Wenn Schalter ; S3 aus ist (Einschieben des naechsten Buchstabens), ; wird die im Text angegebene Geschwindigkeit durch ; acht geteilt, um die acht Spalten schneller herein ; zu schieben. ; Wenn Schalter 4 ausgeschaltet ist, werden die LEDs ; nach der halben Anzeigezeit ausgeschaltet. Die LEDs ; erscheinen dann weniger hell. ; ; Textanzeige: ; Vier verschiedene Textsequenzen koennen im EEPROM ; hinterlegt werden. Jede muss mit 0xFF enden. Als ; Characterset ist 7-Bit-ASCII implementiert, die ; unteren 32 Steuercodes sind mit Grafikzeichen ; belegt. ; Innerhalb des Textes koennen Geschwindigkeits- ; steuernde Zeichen untergebracht werden. Dies sind ; Zeichen zwischen 128 und 254. Sie setzen die Zeit ; zwischen der Ausgabe zweier Zeichen auf 20*(n-128) ; Millisekunden (n=128 setzt auf 20*256 ms = 5 s). ; Abhaengig von den beiden Schaltern S1 und S2 wird ; eine von vier Textsequencen abgespielt. ; Ist Schalter S3 an, wird der Text Zeichen fuer ; Zeichen angezeigt. Ist er aus, dann wird der Text ; mit achtfacher Geschwindigkeit von rechts nach ; links ueber das Display geschoben. ; ; ================================================ ; K O N S T A N T E N Z U M V E R S T E L L E N ; ================================================ ; .equ mux_freq = 50 ; Multiplexfrequenz der Anzeige ; ; ============================================================ ; F E S T E U N D B E R E C H N E T E K O N S T A N T E N ; ============================================================ ; .equ clock = 1000000 ; Interne RC-Generator Frequenz .equ mux_int_freq = 4 * mux_freq ; Interrupt Frequenz fuer MUX .equ presc = 8 ; 16-bit Timer Vorteiler .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 E N ; ============================================ ; ; benutzt: R0 fuer LPM und andere Zwecke auszerhalb Ints, unbenannt ; benutzt: R1..R8 fuer Schiebezwecke auszerhalb Ints, unbenannt ; frei: R9..R14 .def rSreg = R15 ; temporaeres SREG Flagregister .def rmp = R16 ; Vielzweckregister auszerhalb Ints .def rimp = R17 ; Vielzweckregister innerhalb Ints .def rCntDwn = R18 ; Countdown Register innerhalb Ints .def rMux = R19 ; Multiplex-Zeilentreiberregister .def rAct = R20 ; Anzahl Multiplexzyklen bis zum Setzen der T-Flagge .def rChr = R21 ; Zaehler fuer das Schieben der Zeichen .def rLCol = R22 ; Spaltenregister zum Feststellen ob Spalte leer ; frei: R23..R25 ; benutzt: R27:R26 (X) als Zeiger auf Multiplexdaten innerhalb Ints ; benutzt: R29:R28 (Y) als Zeiger auszerhalb Ints ; benutzt: R31:R30 (Z) als Zeiger auszerhalb Ints ; ; ============================================ ; S R A M D E F I N I T I O N E N ; ============================================ ; .DSEG .ORG Sram_Start MuxData: ; Spalteninfo fuer Multiplexen der LEDs .byte 8 ; ; ============================================== ; R E S E T U N D I N T V E K T O R E N ; ============================================== ; .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 Serviceroutine Tc1Capt: in rSreg,SREG ; Retten der Flags ldi rimp,0 ; Anzeige aus out pRow,rimp ld rimp,X+ ; lese oberen Spaltenwert out pColU,rimp ; schreibe oberen Spaltentreiber ld rimp,X+ ; lese unteren Spaltenwert out pColL,rimp ; schreibe unteren Spaltentreiber out pRow,rMux ; Zeilentreiber und Anzeige an lsr rMux ; schiebe Multiplexregister rechts brcc Tc1Capt1 ; kein Ueberlauf, fertig ldi rMux,0x88 ; start with first column ldi XL,LOW(MuxData) ; Neustart des MUX-Zeigers dec rCntDwn ; abwaerts zaehlen brne Tc1Capt1 ; nicht Null, fertig mov rCntDwn,rAct ; Neustart Abwaertszaehler out SREG,rSreg ; Wiederherstellen des SREG set ; setze T-Flagge reti Tc1Capt1: out SREG,rSreg ; stelle SREG wieder her reti ; ; Tc1CmpA schaltet die Anzeige vorzeitig aus Tc1CmpA: ldi rimp,0 ; schreibe Nullen in Zeilentreiber out pRow,rimp reti ; ; ============================================ ; H A U P T P R O G R A M M I N I T ; ============================================ ; Main: ; Init Stapel ldi rmp,HIGH(RAMEND) ; Stapelzeiger auf RAMEND out SPH,rmp ldi rmp,LOW(RAMEND) out SPL,rmp ; Init Multiplexvariablen ldi rMux,0x88 ; Starte mit den obersten Zeilen ldi rAct,50 ; Multiplexzyklen fuer T-Flagge, 1 Sekunde mov rCntDwn,rAct ; Multiplexzyklenzaehler ldi XH,HIGH(MuxData) ; X auf Anfang Multiplexdaten im SRAM ldi XL,LOW(MuxData) ; Init Anzeigeports clr rmp ; alle Ports aus out pColU,rmp ; obere Spalten out pColL,rmp ; untere Spalten out pRow,rmp ; Zeilen ldi rmp,0xFF ; Alle Porttreiber fuer die Anzeige auf Ausgang out pColUD,rmp ; oberer Spaltentreiber out pColLD,rmp ; unterer Spaltentreiber out pRowD,rmp ; Zeilentreiber ; Init Anzeigetest ldi YH,HIGH(MuxData) ; Y zeigt auf Multiplexdaten im SRAM ldi YL,LOW(MuxData) ldi rmp,'A' ; Buchstabe A anzeigen rcall Rmp2Asc ; Z auf Anfang A im Flashspeicher setzen ldi rmp,8 WriteDisp: lpm R0,Z+ st Y+,R0 dec rmp brne WriteDisp ; Init Schalterports clr rmp ; Schalterport auf Eingang out pSwD,rmp ldi rmp,0x0F ; Pull-up-Widerstaende einschalten out pSw,rmp ; Init TC1 als Multiplextimer mit ICR-CTC und Compare A Int ldi ZH,HIGH(comp) ; TC1 CTC-Wert an ICR ldi ZL,LOW(comp) out ICR1H,ZH out ICR1L,ZL lsr ZH ; TC1 Compare A auf Halbzeit ror ZL out OCR1AH,ZH ; TC1 Compare A schreiben out OCR1AL,ZL ldi rmp,0 ; WGM11 und WGM10 auf Null 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 E P R O M ; ============================================ ; .eseg ; Anfang des EEPROM Segments ; Bytes mit 128..254: setze Geschwindigkeit auf (Wert-128), ; wenn Schieben gewaehlt: (Wert-128) / 8 ; Byte 0xFF als Textendmarke .org $0000 ; Text0: .db 4+0x80,' ',0,1,2,3,2,1,0 ; explodieren und implodieren .db 16+0x80,4,5,6,5,4,0,' ' ; Kreuz .db 4+0x80,7,8,9,10,11,12,13,14,7,' ' ; rotieren .db 16+0x80,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30 ; Spirale .db 32+0x80,29,28,27,26,25,24,23,22,21,20,19,18,17,16,' ' ; Spirale rueckwaerts .db 0xFF Text1: .db 32+0x80,"Gerhard Schmidt, Kastanienallee 20, 64289 Darmstadt",0xFF Text2: .db 40+0x80,"Willkommen beim LED-Grab von DG4FAC, Version 1 ",0xFF Text3: .db 64+0x80,"Text nicht programmiert ",0xFF ; ; Ende des EEPROM-Segments .cseg ; ; End of source code ; Copyright info .db "(C)2010 by Gerhard Schmidt " ; menschenlesbar .db "C(2)10 0ybG reahdrS hcimtd " ; wortgerecht ;