;Impulsgenerator für AVR Tiny15 zum Einsatz im Modellbau. ;Es wird aus einem Analogsignal ein Kanalimpuls erzeugt, ;mit dem z.B. ein Soundmodul angesteuert werden kann... ;Auftragsarbeit für Lintronic, (c) 2004 by ...HanneS... ;Anschlussbelegung des Tiny15: ;Pin 1: Reset (über R an +5V) ;Pin 2: Steuereingang für Gas (Analogeingang) ;Pin 3: Trimmeingang für Neutralstellung (Analogeingang) ;Pin 4: GND ;Pin 5: Jumper gegen GND für Arbeitsrichtung (verlängernd/verkürzend) ;Pin 6: Impulsausgang ;Pin 7: NC (nicht belegt) ;Pin 8: +5V ;Damit die Kalibration des internen RC-Oszillators auf 1,6MHz funktionieren kann, ;muss das "Calibrationsbyte" mittels eines ISP-Programms aus dem Signature-Bereich ;des Tiny15 gelesen werden und in die letzten beiden Bytes des Flash-Speicherbereiches ;eingetragen werden. (eigentlich nur in das L-Byte der letzten Word-Zelle) ;Wird das versäumt, stimmt das Timing nicht!!! ;------------------------------------------------------------------------------ ;untere Register: .def null=r1 ;Wert Null .def gasmux=r2 ;ADMUX-Wert für Gaseingang .def trimux=r3 ;ADMUX-Wert für Trimmeingang .def timaus=r4 ;Timer-Interruptfreigabe nur Timer0 .def timein=r5 ;Timer-Interruptfreigabe Timer0 und Timer1 .def sw=r6 ;ADC-Scanwert .def t1vt16=r7 ;Timer1 Vorteiler 1:16 (Wert 9) ;obere Register: .def tmp=r16 ;temporäres Register .def iw=r17 ;Impulswert, aus Analogwerten berechnet .def nlw=r18 ;Nachlaufwert für Kanalimpuls .include"tn15def.inc" .org 0 ;Startadresse ;Vektoren (Sprungtabelle) rjmp RESET ; Reset handler reti ;rjmp EXT_INT0 ; IRQ0 handler reti ;rjmp PIN_CHANGE ; Pin change handler reti ;rjmp TIM1_CMP ; Timer1 compare match rjmp TIM1_OVF ; Timer1 overflow handler (Impulsbreite) rjmp TIM0_OVF ; Timer0 overflow handler (alle 10ms) reti ;rjmp EE_RDY ; EEPROM Ready handler reti ;rjmp ANA_COMP ; Analog Comparator handler reti ;rjmp ADC ; ADC Conversion Handler ; ;Interrupt-Service-Routinen: tim0_ovf: ;ISR alle 10ms, wechselweise Trimmung und Gas einlesen... in r0,admux ;ADC-Quelle (welcher Eingang ist aktiv?) lesen cpse r0,trimux ;Trimm-Eingang? rjmp tempo ;nein, Tempo (Gaseingang)... in sw,adcl ;ja, Trimmung... ADC-Dummy lesen (untere 2 Bits, werden verworfen) in sw,adch ;ADC-Byte lesen (obere 8 Bits, also 0...255 bei 0...5V) lsl sw ;Scannwert (0...255) durch 4 teilen lsl sw ;(0...63) (Auflösung verringern) ldi iw,118 ;Basisimpulslänge vor der Trimmung add iw,sw ;Trimmung zum Basisimpuls addieren (Zielwert: 150) out admux,gasmux ;ADC für nächste Messung auf Gaskanal umschalten reti ;fertig... tempo: ;Gas-Auswertung... in sw,adcl ;ADC-Dummy lesen (untere 2 Bits, werden verworfen) in sw,adch ;ADC-Byte lesen (obere 8 Bits, also 0...255 bei 0...5V) lsl sw ;Scannwert (0...255) durch 4 teilen lsl sw ;(0...63, 32 in Mittelstellung des Trimmpotis) (Auflösung verringern) sbic pinb,1 ;Richtungs-Jumper auf GND? add iw,sw ;nein, offen, Gaswert (Tempo) zum bereits getrimmten Basisimpuls addieren sbis pinb,1 ;Richtungs-Jumper offen? sub iw,sw ;nein, GND, Gaswert (Tempo) vom bereits getrimmten Basisimpuls subtrahieren out admux,trimux ;ADC für nächste Messung auf Trimmkanal umschalten subi iw,(-5) ;große Hysterese - cp iw,nlw ;überschritten? brmi minus3 ;ja... subi iw,2 ;kleine Hysterese - cp iw,nlw ;überschritten? brmi minus1 ;ja... subi iw,8 ;große Hysterese + cp nlw,iw ;überschritten? brmi plus3 ;ja... subi iw,(-3) ;kleine Hysterese + cp nlw,iw ;überschritten? brmi plus1 ;ja... fertig: ;Impuls setzen mov tmp,nlw ;Kopie vom Nachlaufwert com tmp ;invertieren und in out tcnt1,tmp ;Timer1 legen (Timer1 löst bei Überlauf 255->0 Int aus) out timsk,timein ;Int Timer1 aktivieren out tccr1, t1vt16 ;Timer1 mit Vorteiler 16 starten (100kHz, 10µs pro Wert) sbi portb,1 ;Impuls auf H setzen reti minus3: ;Hysterese/Nachlauf dec nlw ;Nachlauf- dec nlw ;Wert minus1: dec nlw ;reduzieren rjmp fertig plus3: inc nlw ;Nachlauf- inc nlw ;Wert plus1: inc nlw ;erhöhen rjmp fertig tim1_ovf: ;Impuls abschalten, Zeit abgelaufen... cbi portb,1 ;Impuls auf GND out timsk,timaus ;Timer1-INT deaktivieren out tccr1,null ;Timer1 stoppen reti ;fertig... ;Programmstart: reset: ;Initialisierung ldi zl,low(flashend*2) ;Pointer auf ldi zh,high(flashend*2) ;Kalibrationsbyte lpm ;nach r0 holen ldi tmp,255 ;Referenz cpse tmp,r0 ;Kalibrationsbyte gültig (<>$ff)? out osccal,r0 ;ja, kalibrieren ldi tmp,1 ;Pull-Up nur am Jumper out portb,tmp ;und L-Pegel an Impulsausgang ldi tmp,2 ;PB1 als out ddrb,tmp ;Ausgang ldi nlw,150 ;bei 1,5ms starten ldi tmp,3 ;Vorteiler 1:64 für Timer0 out tccr0,tmp ;(97,7Hz,10,24ms pro Int.) ldi tmp,(1<