ATtiny44-TPS          

von Ralf Beesner                        
Elektronik-Labor  Projekte   TPS


Das TPS-System weist wegen seines Minimalismus einen hohen Suchtfaktor auf, obwohl man eigentlich komfortablere Systeme gewohnt ist  (aber letztlich ist man dann doch froh, wenn man dank Tippomat und SPS_Emu die Programme nicht Bit für Bit in die TPS  hacken muss. Aber man könnte es…).  Auch mich hat der TPS-Bazillus befallen. Allerdings in der Atmel-Variante; der im Lernpaket verwendete Holtek-Controller war mir zu exotisch. Die AtMega8-Version schien mir auch nicht ideal, weil der AtMega im DIL-Gehäuse recht unförmig ist, man sich beim Aushebeln aus der IC-Fassung ziemlich abmühen muss und viele der 28 Pins ungenutzt bleiben. Die Wahl fiel auf den AtTiny84 bzw. AtTiny44A im DIL14-Gehäuse (der AtTiny44A  ist bei Reichelt neu im Programm und recht preiswert).


Die AtTinies haben allerdings gegenüber dem Holtek-Controller zwei Pins zu wenig. Ich habe kurzerhand zwei Eingangspins eine Doppelfunktion zugewiesen:  Din.3 und ADC.0 sowie Din.4 und ADC.1 können wahlweise als Digital- oder als Analogeingänge abgefragt werden (es dürfte nur wenige Projekte geben, bei denen man in Summe mehr als 4 Eingänge benötigt).

PA0 bis PA3 sind Ausgänge, PA4 bis PA7 Eingänge, Taster 1 liegt an PB0, Taster 2 liegt an PB1, PB2 ist der PWM- Ausgang und PB3 der Reset.
Die Ein- bzw. Ausgänge sind alle auf eine 15-polige einreihige gewinkelte Buchsenleiste geführt, so dass man eine zweite Streifenrasterplatine mit der I/O- Beschaltung direkt anflanschen kann.

 

Die Buchsenleiste ist bei Reichelt als „BL 1X20W8 2,54“ erhältlich – allerdings in 20-poliger Ausführung, 5 Pole sind abgekniffen. Die Buchsenleiste war in der Eagle- Library nicht enthalten, das ersatzweise  im Platinenlayout verwendete Symbol sieht etwas anders aus. Auf dem Foto ist ein provisorischer Tippomat-Adapter angesteckt. Beim fotografierten Prototypen weist der Steckverbinder nur 13 Pole auf, aber wegen des Tippomat habe ich im Nachinein den Reset-Pin noch dazugenommen und ausserdem einen zweiten Masseanschluss, damit beim Stecken immer als erstes die Masseverbindung erfolgt.

 Den Bascom-Code habe ich nicht vollständig verstanden, sondern nur die Portzugriffe geändert. Da die 4bit-Ports für Ausgänge und Eingänge auf dem gleichen 8bit-Port liegen, sind die nicht angesprochenen 4 Bits jeweils über eine Bitmaske weggefiltert. Damit man einen fabrikfrischen AtTiny nicht von 1 MHz Takt auf 8 Mhz Takt umfusen muss, schaltet das Bascom-Programm zur Laufzeit auf 8 MHz um. 

Die 50-ms Waitbefehle, die wohl zum Entprellen der Taster dienen, musste ich auf 40 ms verkleinern, da sonst der Tippomat nicht nicht funktionierte. Vermutlich müssten im Tippomat die 50ms-Waitbefehle etwas verlängert werden, aber ich habe kein Visual Basic, und deshalb habe ich das Bascom-Programm geändert. 
Ich hatte zunächst den Verdacht, dass der RC- Oszillator in meinem  AtTiny84 ungenau ist, aber der erwies sich als unglaublich exakt. Ich habe die TPS alle 10 Sekunden von 1 bis 6 zählen lassen, und nach 60 Minuten war sie immer noch sekundengenau - die Abweichung liegt also unter 0,3 Promille!

(Hinweise zum Tippomat-Timing von B.K: Das Programm wurde nur mit der Holtek-Version getestet und das Timing dabei experimentell angepasst.Beim Mega8 muss das Timing wohl etwas anders gewesen sein. Das macht also Sinn, den AVR bei der Eingabe etwas schneller zu machen.) 

Den geänderten Bascom-Code habe ich noch nicht ausgiebig getestet, aber die Hardwarezugriffe arbeiteten alle wie erwartet, und der übrige Code ist so ziemlich der  gleiche wie bei der AtMega8-Version; deshalb hoffe ich, keine Bugs eingebaut zu haben. Die Beispielprogramme, die im Holtek-Controller fest eingebaut sind, fehlen (wie auch bei der AtMega8-TPS).

Download: Tps44.zip


'--------------------------------------------------------------
' Tasten-programmierbare Steuerung TPS
' ATtiny84 oder AtTiny44, intern 8 MHz, 2 shared ADC, 1 PWM
' AtTiny kann auf 1 MHz gefust bleiben, er wird zur Laufzeit auf 8 MHz
' umgeschaltet
' Bascom Version 1.11.9.6
'--------------------------------------------------------------

' OC0A an PB2 -> nur ein PWM- Ausgang
' S1 = PB0
' S2 = PB1
' Ausgänge PA0...PA3
' Eingänge PA4...PA7
' Analogeingang PA6 -> gleicher Pin wie digitaler Eingang PA6
' Analogeingang PA7 -> gleicher Pin wie digitaler Eingang PA7

' Entprell- Zeiten von 50 ms auf 40 ms geändert; mit 50 ms funktionierte
' der Tippomat nicht

$regfile = "attiny44.dat"
'$regfile = "attiny84.dat"
$crystal = 8000000
$hwstack = 32
$swstack = 32
$framesize = 32


Dim Addr As Byte
Dim Eebyte As Byte
Dim Dat As Byte
Dim Kom As Byte
Dim Adrhi As Byte
Dim Adrlo As Byte
Dim Adrret As Byte
Dim Prog As Byte
Dim Dd As Word

Dim A As Byte
Dim B As Byte
Dim C As Byte
Dim D As Byte


Ddrb = &B00000100 ' PB2 PWM Ausgang, Rest Eingang
Portb = &B00000011 ' Pullups PB0 and PB1
Ddra = &B00001111 ' PA1...PA3 Ausgänge, PA4...PA7 Eingänge
Porta = &B11110000 ' Pullups PA4...PA7


S1 Alias Pinb.0 'Dateneingabe
S2 Alias Pinb.1 'Programmieren

Clkpr = 128 ' Taktumschaltung vorbereiten
Clkpr = 0 ' Teilerfaktor 1 -> 8 MHz
Clkpr = 0 ' zur Sicherheit noch mal


Config Adc = Single , Prescaler = Auto , Reference = Avcc
Start Adc

Config Timer0 = Pwm , Prescale = 8 , Compare A = Clear
Pwm0a = 255
Start Timer0


'Waitms 200

'Test: Zählschleife
'Dat = &H45 : Writeeeprom Dat , 0 'A=5
'Dat = &H52 : Writeeeprom Dat , 1 'C=A
'Dat = &H11 : Writeeeprom Dat , 2 'Por=1
'Dat = &H27 : Writeeeprom Dat , 3 '200 ms
'Dat = &H10 : Writeeeprom Dat , 4 'Port=0
'Dat = &H27 : Writeeeprom Dat , 5 '200 ms
'Dat = &HA2 : Writeeeprom Dat , 6 'C-mal jmp 2
'Dat = &H30 : Writeeeprom Dat , 7 'Ende


'Test: Unterprogramm
'Dat = &H4F : Writeeeprom Dat , 0 'A=15
'Dat = &H52 : Writeeeprom Dat , 1 'C=A
'Dat = &H82 : Writeeeprom Dat , 2 'Adr 32...
'Dat = &HD0 : Writeeeprom Dat , 3 'Call 32+0
'Dat = &H80 : Writeeeprom Dat , 4 'Adr 00...
'Dat = &HA2 : Writeeeprom Dat , 5 'C-mal jmp 2
'Dat = &H30 : Writeeeprom Dat , 6 'Ende
'Unterprogramm ab Adresse 32
'Dat = &H11 : Writeeeprom Dat , 32 'Port=1
'Dat = &H27 : Writeeeprom Dat , 33 '200 ms
'Dat = &H10 : Writeeeprom Dat , 34 'Port=0
'Dat = &H27 : Writeeeprom Dat , 35 '200 ms
'Dat = &H27 : Writeeeprom Dat , 35 '200 ms
'Dat = &HE0 : Writeeeprom Dat , 36 'Return


'Test: Verzweigung, Blinken wenn ADC < 7
'Dat = &H47 : Writeeeprom Dat , 0 'A=7
'Dat = &H51 : Writeeeprom Dat , 1 'B=A
'Dat = &H69 : Writeeeprom Dat , 2 'A=ADC
'Dat = &H82 : Writeeeprom Dat , 3 'Adr 32...
'Dat = &HC2 : Writeeeprom Dat , 4 'if A<B then Adr=Adr+1
'Dat = &HD0 : Writeeeprom Dat , 5 'Call 32+0
'Dat = &H80 : Writeeeprom Dat , 6 'Adr 00...
'Dat = &H90 : Writeeeprom Dat , 7 'Jump 00
'Unterprogramm ab Adresse 32
'Dat = &H11 : Writeeeprom Dat , 32 'Port=1
'Dat = &H27 : Writeeeprom Dat , 33 '200 ms
'Dat = &H10 : Writeeeprom Dat , 34 'Port=0
'Dat = &H27 : Writeeeprom Dat , 35 '200 ms
'Dat = &H27 : Writeeeprom Dat , 35 '200 ms
'Dat = &HE0 : Writeeeprom Dat , 36 'Return

'Test : Tastenabfrage S1
'Dat = &HCC : Writeeeprom Dat , 0 'if S1 = 1 then Adr = Adr + 1
'Dat = &H71 : Writeeeprom Dat , 1 'A = A + 1
'Dat = &H54 : Writeeeprom Dat , 2 'Dout =A
'Dat = &H33 : Writeeeprom Dat , 3 'Adr = Adr - 3



Waitms 200


If S2 = 0 Then
Goto Programmieren
Else
Ausfuehren:
Addr = 0
Do
Readeeprom Eebyte , Addr
Addr = Addr + 1
Dat = Eebyte And 15
Kom = Eebyte / 16
If Kom = 1 Then '1: Direkte Portausgabe
Porta = Dat Or &B11110000
End If
If Kom = 2 Then '2: Wartezeit
If Dat = 0 Then Waitms 1
If Dat = 1 Then Waitms 2
If Dat = 2 Then Waitms 5
If Dat = 3 Then Waitms 10
If Dat = 4 Then Waitms 20
If Dat = 5 Then Waitms 50
If Dat = 6 Then Waitms 100
If Dat = 7 Then Waitms 200
If Dat = 8 Then Waitms 500
If Dat = 9 Then Waitms 1000
If Dat = 10 Then Waitms 2000
If Dat = 11 Then Waitms 5000
If Dat = 12 Then Waitms 10000
If Dat = 13 Then Waitms 20000
If Dat = 14 Then Waitms 30000
If Dat = 15 Then Waitms 60000
End If
If Kom = 3 Then '3: Sprung - relativ
Addr = Addr - 1
Addr = Addr - Dat
End If
If Kom = 4 Then
A = Dat
End If
If Kom = 5 Then
If Dat = 1 Then B = A 'Variablen
If Dat = 2 Then C = A
If Dat = 3 Then D = A
If Dat = 4 Then Porta = A Or &B11110000 'Port
If Dat = 5 Then
If A.0 = 0 Then Porta.0 = 0 Else Porta.0 = 1 'Portbits
End If
If Dat = 6 Then
If A.0 = 0 Then Porta.1 = 0 Else Porta.1 = 1
End If
If Dat = 7 Then
If A.0 = 0 Then Porta.2 = 0 Else Porta.2 = 1
End If
If Dat = 8 Then
If A.0 = 0 Then Porta.3 = 0 Else Porta.3 = 1
End If
If Dat = 9 Then
Dd = A * 17 'PWM
Pwm0a = Not Dd ' NOT dd, weil BASCOM beim Attiny 44 kein Pwm = Clear UP kennt
End If
End If
If Kom = 6 Then
If Dat = 1 Then A = B 'Variablen
If Dat = 2 Then A = C
If Dat = 3 Then A = D
If Dat = 4 Then
A = Pina And &B11110000 'Port
Shift A , Right , 4
End If
If Dat = 5 Then A = Pina.4 'Portbits
If Dat = 6 Then A = Pina.5
If Dat = 7 Then A = Pina.6
If Dat = 8 Then A = Pina.7
If Dat = 9 Then
Dd = Getadc(6) 'ADC
Dd = Dd / 64
A = Dd
End If
If Dat = 10 Then
Dd = Getadc(7) 'ADC
Dd = Dd / 64
A = Dd
End If
End If
If Kom = 7 Then
If Dat = 1 Then A = A + 1
If Dat = 2 Then A = A - 1
If Dat = 3 Then A = A + B
If Dat = 4 Then A = A - B
If Dat = 5 Then A = A * B
If Dat = 6 Then A = A / B
If Dat = 7 Then A = A And B
If Dat = 8 Then A = A Or B
If Dat = 9 Then A = A Xor B
If Dat = 10 Then A = Not A
A = A And 15
End If
If Kom = 8 Then
Adrhi = Dat 'Oberes Nibble der Adresse
End If
If Kom = 9 Then
Addr = Adrhi * 16 'Springe absolut 0...255
Addr = Addr + Dat
End If
If Kom = 10 Then
If C > 0 Then 'C-mal
C = C - 1
C = C And 15
Addr = Adrhi * 16 'Springe absolut 0...255
Addr = Addr + Dat
End If

End If
If Kom = 11 Then
If D > 0 Then ' D-mal
D = D - 1
D = D And 15
Addr = Adrhi * 16 'Springe absolut 0...255
Addr = Addr + Dat
End If

End If
If Kom = 12 Then
If Dat = 1 Then
If A > B Then Addr = Addr + 1
End If
If Dat = 2 Then
If A < B Then Addr = Addr + 1
End If
If Dat = 3 Then
If A = B Then Addr = Addr + 1
End If
If Dat = 4 Then
If Pina.4 = 1 Then Addr = Addr + 1
End If
If Dat = 5 Then
If Pina.5 = 1 Then Addr = Addr + 1
End If
If Dat = 6 Then
If Pina.6 = 1 Then Addr = Addr + 1
End If
If Dat = 7 Then
If Pina.7 = 1 Then Addr = Addr + 1
End If
If Dat = 8 Then
If Pina.4 = 0 Then Addr = Addr + 1
End If
If Dat = 9 Then
If Pina.5 = 0 Then Addr = Addr + 1
End If
If Dat = 10 Then
If Pina.6 = 0 Then Addr = Addr + 1
End If
If Dat = 11 Then
If Pina.7 = 0 Then Addr = Addr + 1
End If
If Dat = 12 Then
If Pinb.0 = 0 Then Addr = Addr + 1
End If
If Dat = 13 Then
If Pinb.1 = 0 Then Addr = Addr + 1
End If
If Dat = 14 Then
If Pinb.0 = 1 Then Addr = Addr + 1
End If
If Dat = 15 Then
If Pinb.1 = 1 Then Addr = Addr + 1
End If

End If
If Kom = 13 Then
Adrret = Addr
Addr = Adrhi * 16 'Call Unterprogramm absolut 0...255
Addr = Addr + Dat
End If
If Kom = 14 Then
Addr = Adrret 'Return
End If
Loop
End If


Programmieren:
Addr = 0
Prog = 0
Do
Adrlo = Addr And 15 'Adresse anzeigen
Porta = Adrlo Or &B11110000
Waitms 300
Porta = 0 Or &B11110000
Waitms 200
Readeeprom Eebyte , Addr
Dat = Eebyte And 15
Kom = Eebyte / 16
Porta = Kom Or &B11110000 'Befehl anzeigen
Do
Loop Until S2 = 1
Waitms 40

Prog = 1 'Phase 1: Befehl anzeigen
Do
If S1 = 0 Then

If Prog = 1 Then
Prog = 2
Kom = 15
End If
If Prog = 2 Then 'Phase 2: Befehl verändert
Kom = Kom + 1
Kom = Kom And 15
Porta = Kom Or &B11110000
End If
If Prog = 3 Then : 'Phase 3: Befehl unverändert, Daten ändern
Prog = 5
Dat = 15
End If
If Prog = 4 Then 'Phase 4: Befehl und Daten geändert
Prog = 5
Dat = 15
End If
If Prog = 5 Then 'Phase 5: Daten verändert
Dat = Dat + 1
Dat = Dat And 15
Porta = Dat Or &B11110000
End If
Waitms 40
Do
Loop Until S1 = 1
Waitms 40
End If

If S2 = 0 Then
If Prog = 3 Then Prog = 7 'nur angezeigt, nicht verändert
If Prog = 1 Then
Porta = Dat Or &B11110000
Prog = 3
End If
If Prog = 4 Then
Porta = 255 - Dat
Prog = 6
End If
If Prog = 2 Then
Porta = Dat Or &B11110000
Prog = 4
End If
If Prog = 6 Then 'nur Kommando wurde verändert
Dat = Dat And 15
Eebyte = Kom * 16
Eebyte = Eebyte + Dat
Writeeeprom Eebyte , Addr
Porta = 255 - 0
Waitms 500
Addr = Addr + 1
Prog = 0
End If
If Prog = 5 Then 'Daten wurden verändert
Dat = Dat And 15
Eebyte = Kom * 16
Eebyte = Eebyte + Dat
Writeeeprom Eebyte , Addr
Porta = 0 Or &B11110000
Waitms 500
Addr = Addr + 1
Prog = 0
End If
If Prog = 7 Then
Addr = Addr + 1
Prog = 0
End If
Waitms 40
Do
Loop Until S2 = 1
Waitms 40
End If
Loop Until Prog = 0
Loop

End



Anpassung für den Tiny24, von Maik Singer

Kürzlich habe also dieses Projekt mit dem ATtiny44 aufgegriffen. Da sich in meiner Kiste jedoch nur ein ATtiny24 fand, habe ich das TPS anhand des BASCOM-Quelltextes und der Ausgabe des Disassemblers in Assemblercode "gequetscht". Dabei habe ich noch eine Fehlererkennung bezüglich der Bereichsüberschreitung des Programmzeigers und des von mir hinzugefügten Stapelspeichers hinzugefügt. Der restliche Funktionsumfang entspricht dem des Tiny44-Projekts. Da ich bisher etwas mehr als die Hälfte des Flashspeichers gefüllt habe(Code: 539 words (1078 bytes)), möchte ich zur nächsten freien Zeitscheibe die Fehlermeldung um eine Variablenanzeige und den Befehlssatz entsprechend dem Projekt http://wkla.dyndns.org//pages/mcs/microcontroller/arduinosps.php erweitern. Die PWM-Steuerung soll für den menschlichen Betrachter (subjektive Lichtstärke-Wahrnehmung) gleichmäßig aussehen. Hier meine Projektdateien. Der Quelltext enthält noch auskommentiert die Ausgabe des Disassemblers. Da dieser das Semikolon als erstes Zeichen der Zeile enthält, lässt er sich leicht entfernen. (z.B.: sed '/^;/d' tps/mytps_t24.asm )

Download: tn24_tps.tar.gz




Elektronik-Labor  Projekte   TPS