' Dieses Programm kann NEC Ferbedienungscodes senden.
' allerdings muss man wissen, dass es nicht die Codes selbst, sondern die Pegelfolgen versendet.
' eigentlich ist es ein Sampler, (wie ein DSO nur Rückwäerts)
' bei den Codes muss also nicht der reale Code eingetragen werden sondern das, was man auch messen würde
'------------------------------------------------------------------------------------------------------------

'    * Logical '0' – a 562.5µs pulse burst followed by a 562.5µs space, with a total transmit time of 1.125ms

'    * Logical '1' – a 562.5µs pulse burst followed by a 1.6875ms space, with a total transmit time of 2.25ms

'-------------------------------------------------------------------------------------------------------------

' Ich hoffe , ihr versteht es
'


$regfile = "m644def.dat"
$crystal = 8000000                                          '0,5uS  @ 2mhz 0,125uS @ 8Mhz
$baud = 9600

$hwstack = 32                                               'default use 32 for the hardware stack
$swstack = 10                                               'default use 10 for the SW stack
$framesize = 40                                             'default use 40 for the frame space




'************************ some vars
Dim Datenfeld(256) As Eram Byte At $0000                    'eigentlich eine Art overlay für den Zugriff auf eram als array
Dim Sendepuffer(16) As Byte
Dim Datenfeld_readpointer As Byte
Dim I As Byte
Dim Wantrepeat As Byte
Dim Waehle_datensatz As Byte
Dim Bitcount As Byte
Dim Tmpword As Word

'*************************************************************************

Dim Sysfreq As Long                                         'in 1000stel Mhz
Sysfreq = _xtal \ 1000

'******************* Taktoption ********************
'teile Grundtakt durch 4 als option zum Stromsparen- Dazu aber auch Crystal anpassen, sonst geht Baud nicht mehr
'bei Bedarf also aktivieren. Wenn Gruntakt 8Mhz ergibt sich dann alo 2 Mhz
'ldi r25,$80
'ldi r24 ,$02
'!out clkpr,r25                                              'CLKPR  Clock Prescale Register
'!out clkpr,r24
'******************* ende Taktoption / Bitte nur atomar ausführen wie hier abgebildet********


'********************** je nach uC / M88 /M644 die jeweils nicht benutzen 2 Zeilen auskommentieren ****
'******************************************************************************************************
' der Anschluss für die IR LED mit Treiberschaltung =  OC0A  für Mega 88 = PD6
'Config Portd.6 = Output
'Portd.6 = 0                                                 ' muss auf 0 sein und so bleiben

' der Anschluss für die IR LED mit Treiberschaltung =  OC0A  für Mega 644 = PB3
Config Portb.3 = Output
Portb.3 = 0                                                 ' muss auf 0 sein und so bleiben

'***** unteres Ende von je nach uC / M88 /M644 die jeweils nicht benutzen 2 Zeilen auskommentieren ****
'******************************************************************************************************

'eine Kontroll Led im sichtbaren Bereich
Config Portc.3 = Output
Kontroll_led Alias Portc.3


'************************ tasten und tasten INT  ************************
'*  An den Tastenports können 1nF Caps gegen GND hilfreich sein /Antiprell bei alten Tastern
' eine Taste an PC2
Config Portc.2 = Input
Portc.2 = 1                                                 ' Pullup ein
Taste1 Alias Pinc.2

Config Portc.4 = Input
Portc.4 = 1                                                 ' Pullup ein
Taste2 Alias Pinc.4

Dim Taste_gedrueckt As Byte
Dim Taste_gedrueckt_alt As Byte

'int2 für Tastenabfrage gemäss http://www.edn.com/file/13261-52605di.pdf
'**** 10nF bis 100nF vom INT Eingang zu GND kann hilfreich sein *****
Config Portb.2 = Input
Portb.2 = 1                                                 ' Pullup ein
Config Int2 = Falling
On Int2 Tasten_int
Enable Int2
'************************ ENDE tasten und tasten INT  ************************


Const Traegerfreq = 38                                      'in khz  38khz = 26,3uS
Const Pulslaenge = 562                                      'in mikrosec


'******************** timer 0 für modulation
'

Tccr0b.cs02 = 0                                             ' set CS00 to 1 to start timer with prescaler 1
Tccr0b.cs01 = 0                                             'wird im Mainloop gestartet und gestoppt
Tccr0b.cs00 = 0

'------------------   4 mal normal port operation = Disconnect
Tccr0a.com0a1 = 0
Tccr0a.com0a0 = 0                                           'com0a0 = 0 = diskonnenct / com0a0 = 1 = toggle
Tccr0a.com0b1 = 0
Tccr0a.com0b0 = 0

'-----------------  Mode 2 = CTC , TOP = OCRA , TOV on Bottom
Tccr0b.wgm02 = 0
Tccr0a.wgm01 = 1
Tccr0a.wgm00 = 0




Tmpword = Sysfreq \ Traegerfreq                             'Sysfreq \ Traegerfreq
Ocr0a = Tmpword
Decr Ocr0a                                                  ' einen subtrahieren
Ocr0a = Ocr0a / 2




'******************** timer 1 für pulslänge


Tccr1b.cs12 = 0                                             'wird durch "Send_data" mit prescaler 1 gestartet
Tccr1b.cs11 = 0                                             ' und durch "T1comparea:" wieder gestoppt
Tccr1b.cs10 = 0

'---------------- ctc Mode 4
Tccr1b.wgm13 = 0                                            ' top =ocr1a
Tccr1b.wgm12 = 1                                            ' update immediate
Tccr1a.wgm11 = 0                                            ' tovr at max
Tccr1a.wgm10 = 0

'--- normal port = disconnect

Tccr1a.com1a1 = 0
Tccr1a.com1a0 = 0

' typconvertierung ist in Bacom immer sehr schwierig

Sysfreq = Sysfreq * Pulslaenge                              ' Berechnung des Timerwertes für  Pulslaenge
Sysfreq = Sysfreq / 1000
Tmpword = Sysfreq
Ocr1a = Tmpword

On Oc1a T1comparea
Enable Oc1a


Enable Interrupts

'******************************** begin Main **************************************

Do

Tccr0b.cs00 = 0                                             ' Modulationstimer stoppen

Kontroll_led = 0                                            ' led aus
Do

' *************************lets go for sleep / Powerdown
' diesen Block während der Testphase am besten auskommentieren

If Taste_gedrueckt_alt = 0 Then                             ' nix gedrückt
Config Int2 = Low Level
Powerdown
Config Int2 = Falling

End If
' ******** unteres Ende des Powerdown Blocks


Loop Until Taste_gedrueckt <> 0                             ' meldung von INT2 dass eine Taste gefrückt wurde

Kontroll_led = 1                                            ' led ein

Tccr0b.cs00 = 1                                             ' Modulationstimer starten

If Taste_gedrueckt = 1 Then Waehle_datensatz = 5
If Taste_gedrueckt = 2 Then Waehle_datensatz = 7            'Die Auswahl für den gewünschten Datensatz ist nun in "Waehle_datensatz" / erster Datensatz = 0
Taste_gedrueckt_alt = Taste_gedrueckt                       ' zwischenspeichern für repeaterkennung
Taste_gedrueckt = 0                                         ' und wieder zurückstellen bis neue Taste gedrüch wurde



Gosub Copy_from_eprom                                       ' holt den Datensatz in den Sendepuffer
Gosub Send_data

Waitms 150                                                  'das beinflusst hauptsächlich die Wiederholfrequenz für repeat

'************ teste für wantrepeat  ****************************
'auf den Repeatcode lt. NEC Protocol wurde verzichtet .
'stattdessen testen wir per  "Gosub Tasten_int " nochmal ob noch eine Taste gedrückt ist.
'ob nun ein Datensatz in den Genuss dieser Funktion kommt oder nicht wird im letzen Bit
'jedes Datensatzes definiert. Steht dort eine 1 wird repetiert. Bei null dann eben nicht

If Wantrepeat = 1 Then Gosub Tasten_int                     ' teste ob taste noch gedrückt


Loop
End

'***************************** end Main *******************************************

'********************* sub Copy_from_eprom to sendepuffer
Copy_from_eprom:



For I = 1 To 16
Datenfeld_readpointer = Waehle_datensatz * 16
Datenfeld_readpointer = Datenfeld_readpointer + I
Sendepuffer(i) = Datenfeld(datenfeld_readpointer )
Next I

'  ********* nur ein Debug Block ************* im Normalbetrieb auskommentieren !
'Print
'Print "**"
'Print "Waehle_datensatz " ; Waehle_datensatz
'For I = 1 To 16
'Print Hex(sendepuffer(i)) ; " - " ; Bin(sendepuffer(i))
'Next I
'  ******** end debugblock    *****************

Wantrepeat = Sendepuffer(16).0                              'Bit 0 aus dem 16ten Datenbyte als Kennung ob für  Taste Repeatcode erwünscht
Sendepuffer(16).0 = 0                                       'Bit 0 aus 16 Datenbyte für den sendestream wieder auf 0 stellen

Return
'********************* ENDE sub Copy_from_eprom

'********************* sub  Send_data to ir diode
Send_data:

Bitcount = 8
Datenfeld_readpointer = 1
I = 0

Timer1 = 0                                                  ' Timer nochmal auf 0 stellen
Tccr1b.cs10 = 1                                             'Timer  für  Sendetaktung aktivieren
Do
Loop Until Tccr1b.cs10 = 0                                  'endless Loop bis Timer wieder von T1comparea gestoppt wurde

Return
'********************* ENDE sub  Send_data







'***************** int2 = taste gedrueckt
Tasten_int:
' die gedrückte Taste geht auf null wegen der Pullups und Taster gegen GND
Taste_gedrueckt.0 = Not Taste1
Taste_gedrueckt.1 = Not Taste2
                            ' lieber positiv denken und Tasten invertieren
'taste 1 ergibt nun eine 1 , taste 2 ergibt eine 2, keine Taste eine null
                                     '
Return



'***************************  sub t1 comparea
T1comparea:


If Datenfeld_readpointer < 17 Then
Bitcount = Bitcount - 1


Tccr0a.com0a0 = Sendepuffer(datenfeld_readpointer).bitcount

If Bitcount = 0 Then                                        '
Bitcount = 8
Datenfeld_readpointer = Datenfeld_readpointer + 1
End If

Else

Incr I                                                      'hier noch 68 fillsamples damit insgesamt 196 samples = 108ms lang

If I = 68 Then
Tccr1b.cs10 = 0                                             'Timer1  für  Sendetaktung deaktivieren weil fertig

End If

End If

Return

'************************ end sub t0 comparea



'******************************* NEC Protocol Notizen
' siehe hierzu auch http://wiki.altium.com/display/ADOH/NEC+Infrared+Transmission+Protocol

'    * a 9ms leading pulse burst (16 times the pulse burst length used for a logical data bit) = 16 Samples

'    * a 4.5ms space   = 8 samples

'    * the 8-bit address for the receiving device   'bei nullen 16Samples / bei einsen 24 samples

'    * the 8-bit logical inverse of the address

'    * the 8-bit command

'    * the 8-bit logical inverse of the command

'    * a final 562.5µs pulse burst to signify the end of message transmission.

'------------------------------------------------------------------------------------------------------------

'    * Logical '0' – a 562.5µs pulse burst followed by a 562.5µs space, with a total transmit time of 1.125ms

'    * Logical '1' – a 562.5µs pulse burst followed by a 1.6875ms space, with a total transmit time of 2.25ms

'-------------------------------------------------------------------------------------------------------------

'   * ein Paket ist iclusive der Pause am Ende immer 108ms lang   = 192 Samples
'

' datensätze eeprom
' 0 pr+
' 1 pr-
' 2 epi
' 3 ok
' 4 tv/radio
' 5 mute
' 6 vol+
' 7 vol-
' 8 !exit
'9 audio
'10 empty1
'11 empty2
'12 empty3


'progplus code   0001 0010 1110 1110 0000 0000 1111 1111 = 16 bytes  = 121 Takte
'pegelfolge =
'11111111111111110000000010101010001010100010100010001000101000100010001010101010101010101000100010001000100010001000100010

'volminus code   0001 0010 1110 1110 1100 0000 0011 1111

'11111111111111110000000010101010001010100010100010001000101000100010001010001000101010101010101010001000100010001000100010



$eeprom

Progplus:
Data &B11111111                                             '8 Zeiteinheiten H zu je 562uS
Data &B11111111                                             '8 Zeiteinheiten H zu je 562uS  = insgesamt 8992 uS H
Data &B00000000                                             '8 Zeiteinheiten L zu je 562uS  = insgesamt 4496 uS L
Data &B10101010
Data &B00101010
Data &B00101000
Data &B10001000
Data &B10100010
Data &B00100010
Data &B10101010
Data &B10101010
Data &B10001000
Data &B10001000
Data &B10001000
Data &B10001000
Data &B10000001


Progminus:
Data &B11111111
Data &B11111111
Data &B00000000
Data &B10101010
Data &B00101010
Data &B00101000
Data &B10001000
Data &B10100010
Data &B00100010
Data &B10001010
Data &B10101010
Data &B10101000
Data &B10001000
Data &B10001000
Data &B10001000
Data &B10000001                                             '  bit0 immer als 0 übertragen / 1 bedeutet repeat=ein



Epi:
Data &B11111111
Data &B11111111
Data &B00000000
Data &B10101010
Data &B00101010
Data &B00101000
Data &B10001000
Data &B10100010
Data &B00100010
Data &B10101010
Data &B00101010
Data &B10100010
Data &B00100010
Data &B10001000
Data &B10001000
Data &B10000000                                             '  bit0 immer als 0 übertragen / 1 bedeutet repeat=ein



Ok:
Data &B11111111
Data &B11111111
Data &B00000000
Data &B10101010
Data &B00101010
Data &B00101000
Data &B10001000
Data &B10100010
Data &B00100010
Data &B10001000
Data &B10001000
Data &B10001010
Data &B10101010
Data &B10101000
Data &B10001000
Data &B10000000                                             '  bit0 immer als 0 übertragen / 1 bedeutet repeat=ein



Tvradio:
Data &B11111111
Data &B11111111
Data &B00000000
Data &B10101010
Data &B00101010
Data &B00101000
Data &B10001000
Data &B10100010
Data &B00100010
Data &B10101010
Data &B10101000
Data &B10100010
Data &B00100010
Data &B00100010
Data &B00101000
Data &B10000000                                             '  bit0 immer als 0 übertragen / 1 bedeutet repeat=ein



Mute:
Data &B11111111
Data &B11111111
Data &B00000000
Data &B10101010
Data &B00101010
Data &B00101000
Data &B10001000
Data &B10100010
Data &B00100010
Data &B10101000
Data &B10001010
Data &B10101000
Data &B10001010
Data &B10001000
Data &B10001000
Data &B10000000                                             '  bit0 immer als 0 übertragen / 1 bedeutet repeat=ein



Volplus:
Data &B11111111
Data &B11111111
Data &B00000000
Data &B10101010
Data &B00101010
Data &B00101000
Data &B10001000
Data &B10100010
Data &B00100010
Data &B10100010
Data &B10101010
Data &B10100010
Data &B10001000
Data &B10001000
Data &B10001000
Data &B10000001                                             '  bit0 immer als 0 übertragen / 1 bedeutet repeat=ein



Volminus:
Data &B11111111
Data &B11111111
Data &B00000000
Data &B10101010
Data &B00101010
Data &B00101000
Data &B10001000
Data &B10100010
Data &B00100010
Data &B10001000
Data &B10101010
Data &B10101010
Data &B10001000
Data &B10001000
Data &B10001000
Data &B10000001                                             '  bit0 immer als 0 übertragen / 1 bedeutet repeat=ein

!Exit:
Data &B11111111
Data &B11111111
Data &B00000000
Data &B10101010
Data &B00101010
Data &B00101000
Data &B10001000
Data &B10100010
Data &B00100010
Data &B10001000
Data &B10100010
Data &B00101010
Data &B10101000
Data &B10101000
Data &B10001000
Data &B10000000                                             '  bit0 immer als 0 übertragen / 1 bedeutet repeat=ein


Audio:
Data &B11111111
Data &B11111111
Data &B00000000
Data &B10101010
Data &B00101010
Data &B00101000
Data &B10001000
Data &B10100010
Data &B00100010
Data &B10001000
Data &B10001010
Data &B10101010
Data &B10101000
Data &B10001000
Data &B10001000
Data &B10000000                                             '  bit0 immer als 0 übertragen / 1 bedeutet repeat=ein



Empty:
Data &B00000000
Data &B00000000
Data &B00000000
Data &B00000000
Data &B00000000
Data &B00000000
Data &B00000000
Data &B00000000
Data &B00000000
Data &B00000000
Data &B00000000
Data &B00000000
Data &B00000000
Data &B00000000
Data &B00000000
Data &B00000000                                             '  bit0 immer als 0 übertragen / 1 bedeutet repeat=ein

Empty2:
Data &B00000000
Data &B00000000
Data &B00000000
Data &B00000000
Data &B00000000
Data &B00000000
Data &B00000000
Data &B00000000
Data &B00000000
Data &B00000000
Data &B00000000
Data &B00000000
Data &B00000000
Data &B00000000
Data &B00000000
Data &B00000000


Empty3:
Data &B00000000
Data &B00000000
Data &B00000000
Data &B00000000
Data &B00000000
Data &B00000000
Data &B00000000
Data &B00000000
Data &B00000000
Data &B00000000
Data &B00000000
Data &B00000000
Data &B00000000
Data &B00000000
Data &B00000000
Data &B00000000                                             '  bit0 immer als 0 übertragen / 1 bedeutet repeat=ein