'******************************************************************************* '************************* Funkdatenanzeige ********************************** '****************** bitte das RFM12-Modul anschliessen ************************* '******************************************************************************* 'name : Funkdatenanzeige_V0.1.bas 'copyright : (c) 07.11.2018 jep 'purpose : Anzeigen was gesendet wird, max. 15 Bytes 'micro : Atmel 1284P-PU ' 'Changelog: : ' 'offene Probleme : '------------------------------------------------------------------------------- $regfile = "m1284Pdef.dat" ' ATMEL Mega128PU $crystal = 20000000 ' externer 20 MHz-Clock ohne Divisor $hwstack = 40 ' default use 32 for the hardware stack $swstack = 64 ' default use 10 for the SW stack $framesize = 40 ' default use 40 for the frame space $lib "glcdKS108.lib" ' some routines to control the display are in the glcdKS108.lib file $baud = 115200 Declare Sub Rfm12_init Declare Function Spitransfer(byval Dataout As Word) As Word '================ Tasten konfigurieren ============================== Config Portb.4 = Input 'Taste UP Portb.4 = 1 'Pullup Up Alias Pinb.4 Config Portb.3 = Input 'Taste Down Portb.3 = 1 'Pullup Down Alias Pinb.3 Config PortB.2 = Input 'Taste LEFT PortB.2 = 1 'Pullup Links Alias Pinb.2 Config Portb.1 = Input 'Taste RIGHT Portb.1 = 1 'Pullup Rechts Alias Pinb.1 Config Portb.0 = Input 'Taste OK / Enter Portb.0 = 1 'Pullup Ok Alias Pinb.0 Config DEBOUNCE = 20 '20 ms entprellen '======================== SPI des ATmega1284P ==================================== Mosi Alias Portb.5 Miso Alias Pinb.6 Sck Alias Portb.7 Ss Alias PortD.3 Config Sck = Output 'SCK ----> SCK (RFM12B) Config Mosi = Output 'MOSI ----> SDI (RFM12B) Config Miso = Input 'MISO <---- SDO (RFM12B) Config Ss = Output 'Slave select 'CONFIG SPI = soft , Din = PORTB.6 , Dout = PortB.5 , clock = PortB.7 , SS = PortD.3 'CONFIG SPI = HARD , INTERRUPT = ON , DATA_ORDER = MSB , MASTER = YES , POLARITY = LOW , PHASE = 0 , CLOCKRATE = 16 , NOSS = 0 , SPIIN = 0 'spiinit '==================== LCD Grafik-Display 128 x 64 =================== Config Graphlcd = 128 * 64sed , Dataport = Porta , Controlport = Portc , Ce = 3 , Ce2 = 4 , Cd = 6 , Rd = 5 , Reset = 2 , Enable = 7 Dim X As Byte , Y As Byte , Z1 As Byte , Z2 As Byte Dim Anzeige as Byte Anzeige = "H" Cls Setfont Font8x8 '_______________________________________________________________________________ '========= Hier werden die zu empfangenen Bytes (15, max 50) abgelegt ========== ' 1 2 3 4 5 6 7 8 9 '+----+----+----+----+----+----+----+----+----+ '| Eingangsbytes | '+----+----+----+----+----+----+----+----+----+ '|LENe|DABe|SABe|CDBe|Data| Daten |CRC2|CRC1| '+----+----+----+----+----+----+----+----+----+ ' Const Maxanzahldatenbytes = 16 'Datenmenge max. 15 (+1 Puffer) DIM Irq_anzahlempfangsbytes As Byte 'Zähler für die empfangenen Bytes Dim Irq_empfangsbytes(Maxanzahldatenbytes + 6) As Byte 'Empfangspuffer während Empfang Dim Irq_anzahlbytemax as Byte Dim Irq_Akt_byte As Byte Dim Empfangsbytes_vorhanden As Bit Dim CRC16_eh as Byte Dim CRC16_el as Byte Dim Crc_16e as Word 'CRC16 bei Empfang Dim CRC_16ger as Word 'gerechneter CRC Dim CRC as string * 5 Dim PN as Byte 'Paketnummer ' 'die Quittung besteht aus 4 Bytes ' 1 2 3 4 '+----+----+----+----+ '| Sendebytes( ) | '+----+----+----+----+ '|LENs|DABs|SABs|CDBs| '+----+----+----+----+ ' '================== Interrupt für den Empfang aktivieren ======================= Config PinD.2 = Input 'Int0 PortD.2 = 1 'Pullup Nirq Alias PinD.2 Config Int0 = Falling On Int0 RFM_Funkirq Enable Int0 Disable Interrupts 'alle Interrupts noch stoppen '======== Timerinterupt für Zeitbegrenzung Interruptempfang einstellen =========== Config Timer0 = Timer , Prescale = 1024 Const Timer0_preload = 255 -(8 * 20000000 / 1024 * 4800) 'für 2 Bytes: gilt für 20 MHz und 4800 Baud On Timer0 Timer0_irq 'beim Interrupt Empfang stoppen Enable Timer0 'Timer0 Interrupt freigeben Stop Timer0 Const Power_down = &H8203 Dim Wakeup_timer As Word Wakeup_timer = &HE5A8 'r = 5, m = 168 --> ca. 5 sec 'Prinzip: ' ' max. Empfangslänge ' |<----------------------------->| ' | | ' | Empfangslänge | ' |<--------------------->| | ' | | | ' +---+---+---+---+---+---+ | ' empfangener Datensatz | 1 | 2 | | | |CRC| | ' +---+---+---+---+---+---+ | ' | | | ' | | | ' Datenpuffer = max. empfangener Datensatz x Anzahl Datensätze | v | ' |<-------- Datensatz 1 -------->|<-------- Datensatz 2 -------->v<-------- Datensatz 3 -------->|<---- Datensatz 4 ' +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ ' | 1 | 2 | | | | | | | 1 | 2 | | | | | | | 1| 2 | | | | | | | 1 | 2 | | | | ' +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ ' | | ' | | ' v v ' +---+---+---+---+---+---+---+ --+ ' Anzeigepuffer | 1 | 2 | 3 | 4 | D | D |CRC| | ' +---+---+---+---+---+---+---+ -+ Const max_Empfangslaenge = Maxanzahldatenbytes + 6 'Datenbytes + Overhead Const max_Empfangssaetze = 32 'Anzahl Empfangssätze Const i_max = max_Empfangslaenge * max_Empfangssaetze 'sind 32 Sätze zu 21 Bytes Dim Datenpuffer(i_max)as Byte Dim Anzeigepuffer(max_Empfangslaenge) as Byte Dim LENe as Byte at Anzeigepuffer(1) Overlay 'Längenbyte Dim DABe as Byte at Anzeigepuffer(2) Overlay Dim SABe as Byte at Anzeigepuffer(3) Overlay DIM CDBe as Byte at Anzeigepuffer(4) Overlay Dim Anzahlbyte_e as Byte Dim ACKText as string * 5 Dim Empfang_aktiv as Byte Dim E_aktiv as string * 3 Dim Empfangssatz_Nr as Word Dim Empfangssatz_Nr_nachfuehren as Byte Dim Puffersatz_Nr as Word Dim D as Word Dim i as Word 'Index für Datenpuffer -> Anzeigepuffer Dim k as Byte Dim m as Byte Dim n as Word 'Index für IRQ_Empfangsbytes -> Datenpuffer Dim R as Word Dim z as Byte Dim w as Byte Const L = "L" Const H = "H" Const Printerausgabe = 1 '1 = Printerausgabe; 0 = keine Ausgabe ' * ' *********** ' **************************** ' ******************************************** ' ************************************************************* ' ********************************************************************** '********************************* START ************************************* Programmstart: w = Maxanzahldatenbytes - 1 Print "===========================" Print " Funkdatenanzeige V0.1" Print Print "max. Anzahl Datenbytes: " ; w Print "max. Anzahl Datensätze: " ; max_Empfangssaetze Print "===========================" Print Print Cls Lcdat 1 , 1 , "Funkdatenanzeige" Line(0 , 12) -(127 , 12) , 1 'make line LCDAT 3 , 1 , "Funkdatenanzeige" Lcdat 4 , 1 , " V0.1.bas " LCDat 5 , 1 , " 115200 Baud " Lcdat 7 , 1 , "max. Daten: " ; w Lcdat 8 , 1 , "max. Saetze: " ; max_Empfangssaetze for i = 0 to i_max Datenpuffer(i) = " " 'Puffer löschen next i wait 3 gosub RFM12_init IRQ_akt_Byte = 0 Empfangsbytes_vorhanden = 0 i = 0 n = 0 cls Lcdat 2 , 1 , " RFM 12 ist " Lcdat 4 , 1 , " initialisiert " wait 2 enable Interrupts 'Auf neue Anfangssequenz warten r = Spitransfer(&H82c8) 'Empfänger aktivieren r = Spitransfer(&Hca83) 'FIFO einstellen/aktivieren Empfang_aktiv = 1 E_aktiv = "ON " gosub Anzeigen 'damit dann etwas steht '************************** Hauptprogramm ************************************* Do Debounce Up , 0 , nDaten , Sub Debounce Down , 0 , vDaten , Sub Debounce Links , 0 , setDezimal , Sub Debounce Rechts , 0 , setHex , Sub Debounce Ok , 0 , Start_Stop , Sub #if Printerausgabe = 1 if Empfangsbytes_vorhanden = 1 Then 'vom Funk sind Daten vorhanden Print "neue Funkdaten" Print Empfangsbytes_vorhanden = 0 end if #endif if Empfangssatz_Nr_nachfuehren = 1 then Lcdat 3 , 1 , " " Lcdat 3 , 1 , Empfangssatz_Nr Empfangssatz_Nr_nachfuehren = 0 End if Loop '******************************************************************************* nDaten: i = i + max_Empfangslaenge 'nächste Empfangssequenz if i = i_max then i = 0 'max. x_max Empfangssequenzen Puffersatz_Nr = i \ max_Empfangslaenge Print "Puffersatz-Nr.: " ; Puffersatz_Nr R = Memcopy(Datenpuffer(i) , Anzeigepuffer(1) , max_Empfangslaenge) 'in Anzeigepuffer umkopieren ' if i = i_max then i = 0 'max. x_max Empfangssequenzen gosub Anzeigen 'und anzeigen Return '------------------------------------------------------------------------------- vDaten: i = i - max_Empfangslaenge 'vorhergehende Empfangssequenz if i => 32000 then i = i_max - max_Empfangslaenge 'ist negativ --> wird maximum Puffersatz_Nr = i \ max_Empfangslaenge Print "Puffersatz-Nr.: " ; Puffersatz_Nr ' if i => 32000 then i = i_max - max_Empfangslaenge 'ist negativ --> wird maximum R = Memcopy(Datenpuffer(i) , Anzeigepuffer(1) , max_Empfangslaenge) 'in Anzeigepuffer umkopieren gosub Anzeigen 'und anzeigen Return '------------------------------------------------------------------------------- setDezimal: Anzeige = L 'ist Anzeige in Dezimal gosub Anzeigen Return '------------------------------------------------------------------------------- setHEX: Anzeige = H 'ist Anzeige in HEX gosub Anzeigen Return '------------------------------------------------------------------------------- Start_Stop: Debounce Up , 0 , Loeschen Debounce Down , 0 , Nichts Debounce Links , 0 , Nichts Debounce Rechts , 0 , Nichts Debounce Ok , 0 , On_Off goto Start_Stop Nichts: Return Loeschen: for i = 0 to i_max Datenpuffer(i) = " " 'Puffer löschen next i gosub CLRAnzeigepuffer 'Anzeigepuffer löschen i = 0 n = 0 Puffersatz_Nr = 0 gosub Anzeigen Return On_Off: If Empfang_aktiv = 1 then disable Interrupts Empfang_aktiv = 0 'Merker E_aktiv = "OFF" Else gosub RFM12_init 'neu starten enable Interrupts Empfang_aktiv = 1 E_aktiv = "ON " End if gosub Anzeigen Return '------------------------------------------------------------------------------- CLRAnzeigepuffer: for w = 1 to max_Empfangslaenge Anzeigepuffer(w) = 0 'Puffer mit 0 füllen next w Return '--------------------------------- Anzeige ------------------------------------- Anzeigen: Anzahlbyte_e = Anzeigepuffer(1) + 1 'total Anzahl + LEN Print For w = 1 to Anzahlbyte_e Print Hex(Anzeigepuffer(w)) ; "-" ; next w Print "<" CRC_16e = makeint(Anzeigepuffer(Anzahlbyte_e - 1) , Anzeigepuffer(Anzahlbyte_e)) Y = Anzeigepuffer(1) - 1 'Datenlänge über alles ohne CRC16 CRC_16ger = Crc16(Anzeigepuffer(1) , Y ) 'CRC16 gerechnet If Anzeigepuffer(Anzeigepuffer(1)) <> Low(crc_16ger) Then CRC = "No" Goto Anzeigen1 End if If Anzeigepuffer(Anzeigepuffer(1) + 1) <> High(crc_16ger) Then CRC = "No" Goto Anzeigen1 End if CRC = "OK" Anzeigen1: Print "CRChigh: " ; Hex(Anzeigepuffer(Anzeigepuffer(1) + 1)) ; " " ; Hex(High(crc_16ger)) Print "CRClow: " ; Hex(Anzeigepuffer(Anzeigepuffer(1))) ; " " ; Hex(Low(crc_16ger)) if Anzeige = H then 'ist HEX-Anzeige cls 'Display löschen Lcdat 1 , 1 , E_aktiv Lcdat 1 , 32 , "S-Adr:" ; Hex(SABe) ; " " ; SABe Lcdat 2 , 1 , Puffersatz_Nr Lcdat 2 , 32 , "E-Adr:" ; Hex(DABe) ; " " ; DABe Lcdat 3 , 1 , " " 'Bereich löschen Lcdat 3 , 1 , Empfangssatz_Nr Lcdat 3 , 32 , "L" ; chr(132) ; "nge:" ; Hex(LENe) ; " " ; LENe Line(26 , 0) -(26 , 24) , 1 'senkrechte Trennlinie if CDBe.7 = 0 and CDBe.6 = 0 then ACKText = "nack" 'Senderanforderung if CDBe.7 = 0 and CDBe.6 = 1 then ACKText = " ack" 'Senderanforderung if CDBe.7 = 1 and CDBe.6 = 0 then ACKText = "NACK" 'Quittung if CDBe.7 = 1 and CDBe.6 = 1 then ACKText = " ACK" 'Quittung PN = CDBe and &H0F 'Paketnummer ausmaskieren Lcdat 4 , 1 , "CDB:" ; AckText ; " " ; CDBe.5 ; CDBe.4 ; " P:" ; PN k = 1 'Kolonne der Anzeige z = 5 'Zeile der Anzeige if Anzeigepuffer(1) = 0 then Anzeigepuffer(1) = 2 for w = 5 to Anzeigepuffer(1) - 1 'Daten, ohne CRC Lcdat z , k , Hex(Anzeigepuffer(w)) ; "-" '5. Zeile, 5...9. Zeichen k = k + 24 '= 1....5. Datenbyte If w = 9 then '6. Zeile, 10...14. Zeichen k = 1 '= 6....10. Datenbyte z = z + 1 End if If w = 14 then '7. Zeile, 15....19. Zeichen k = 1 '= 10....15. Datenbyte z = z + 1 End if next w if LENe > 3 then Lcdat 8 , 1 , "CRC:" ; Hex(Anzeigepuffer(Anzeigepuffer(1) + 1)) ; Hex(Anzeigepuffer(Anzeigepuffer(1))) ; " " ; Hex(CRC_16ger) ; " " ; CRC End if if Anzeige = L then 'Anzeige in ASCII cls 'Display löschen Lcdat 1 , 1 , E_aktiv Lcdat 1 , 32 , "S-Adr:" ; Hex(SABe) ; " " ; SABe Lcdat 2 , 1 , Puffersatz_Nr Lcdat 2 , 32 , "E-Adr:" ; Hex(DABe) ; " " ; DABe Lcdat 3 , 1 , " " 'Bereich löschen Lcdat 3 , 1 , Empfangssatz_Nr Lcdat 3 , 32 , "L" ; chr(132) ; "nge:" ; Hex(LENe) ; " " ; LENe Line(26 , 0) -(26 , 24) , 1 'senkrechte Trennlinie if CDBe.7 = 0 and CDBe.6 = 0 then ACKText = "noak" 'Senderanforderung if CDBe.7 = 0 and CDBe.6 = 1 then ACKText = "jaak" 'Senderanforderung if CDBe.7 = 1 and CDBe.6 = 0 then ACKText = "NACK" 'Quittung if CDBe.7 = 1 and CDBe.6 = 1 then ACKText = " ACK" 'Quittung PN = Anzeigepuffer(4) and &H0F 'Paketnummer ausmaskieren Lcdat 4 , 1 , "CDB:" ; AckText ; "-" ; CDBe.5 ; CDBe.4 ; " P:" ; PN k = 1 'Kolonne der Anzeige z = 5 'Zeile der Anzeige for w = 5 to Anzeigepuffer(1) - 1 'sind nur die Daten Lcdat z , k , chr(Anzeigepuffer(w)) '5. Zeile k = k + 24 If w = 9 then '6. Zeile k = 1 z = z + 1 End if If w = 14 then '7. Zeile k = 1 z = z + 1 End if next w if LENe > 3 then Lcdat 8 , 1 , "CRC:" ; Hex(CRC_16e) ; " " ; Hex(CRC_16ger) ; " " ; CRC End if Return '***************** Empfangs-Interrupt des Funkmoduls RFM12 ******************** Rfm_funkirq: Disable Int0 'während Interruptbehandlung ausschalten Timer0 = Timer0_preload Start Timer0 'Start Zeitüberwachung (Bitweise) Incr Irq_akt_byte 'aktueller Bytezähler erhöhen (Startwert ist 0) Irq_empfangsbytes(irq_akt_byte) = Spitransfer(&Hb000) 'Empfangsbyte holen und abspeichern If Irq_akt_byte = 1 Then Irq_anzahlbytemax = Irq_empfangsbytes(1) + 1 'im ersten Byte steht die Anzahl folgender Datenbytes End If If Irq_akt_byte = Irq_anzahlbytemax Then 'max. Anzahl Bytes erreicht Stop Timer0 R = Memcopy(irq_empfangsbytes(1) , Datenpuffer(n) , Irq_anzahlbytemax) 'umkopieren n = n + max_Empfangslaenge 'nächster Slot if n = i_max then n = 0 'wenn Puffer voll wieder von vorne Empfangssatz_Nr = n / max_Empfangslaenge Empfangsbytes_vorhanden = 1 'Merker setzen Empfangssatz_Nr_nachfuehren = 1 Irq_akt_byte = 0 'Bytezähler löschen R = Spitransfer(&Hca81) 'FIFO FILL zurücksetzen R = Spitransfer(&Hca83) 'FIFO FILL aktivieren Eifr.intf0 = 1 'Eventuell anstehenden Interrupt löschen End If Enable Int0 Return Timer0_irq: Stop Timer0 'Interrupt-Ueberwachung abgelaufen --> Stop Irq_akt_byte = 0 'Bytezähler löschen Empfangsbytes_vorhanden = 0 'Eventuellen Merker löschen R = Spitransfer(&Hca81) 'FIFO FILL zurücksetzen R = Spitransfer(&Hca83) 'FIFO FILL aktivieren Eifr.intf0 = 1 'Eventuell anstehenden Interrupt löschen #if Printerausgabe = 1 Print "Timeout" #endif Return '_______________________________________________________________________________ '( Function Spitransfer(byval Dataout As Word) As Word Local Dat_in_h as Byte Local Dat_in_l as Byte SPIINIT Dat_in_h = Spimove(High(Dataout)) Dat_in_l = Spimove(Low(Dataout)) Spitransfer = makeint(Dat_in_l , Dat_in_h) End Function ') Function Spitransfer(byval Dataout As Word) As Word Local Nspi As Integer Local Dspi As Integer Local Dmiso As Word Ss = 0 Dmiso = 0 For Nspi = 1 To 16 Dspi = Dataout And &H8000 If Dspi = 0 Then Mosi = 0 Else Mosi = 1 End If Dataout = Dataout * 2 Dmiso = Dmiso * 2 Dmiso = Dmiso + Miso Sck = 1 Waitus 1 Sck = 0 Next Nspi Ss = 1 Spitransfer = Dmiso End Function '_______________________________________________________________________________ 'RFM-Initialisierung Sub Rfm12_init Local Wert As Word X = 0 Restore Datainit3 'Initialisierungsfolge Do Read Wert D = Spitransfer(wert) Incr X Loop Until Wert = 0 Waitms 200 R = Spitransfer(&H0000) End Sub '_______________________________________________________________________________ End '******************************************************************** ' Programmende $include "font8x8.font" 'FONT-files hinzufügen '--------------------------------------------------- 'Funkmodul Initialisierungsdaten mit 9600 Baud Datainit3: Data &H80E8% ' Enable: 868 Mhz;XTAL cap=12pf; TX-Register; RX-Fifo Data &H82D9% ' Enable: Receiver; Crystal Osc; Base Band Block; Synthesizer, Disable Low-bat Detector; Transmitter; Wake-Up-Timer; Clock output Pin Data &HA67C% ' &Ha67c=frequenz 434,15 Mhz oder z.B. &HA538 für 433,34 Mhz Data &HC647% ' &Hc647=Datenrate '4.8kbps; C623=9600kbps; C611 =19200 Data &H95C0% ' Vdi , Fast , 67 kHz , 0db , -79dbm !!!!!!!!!! Data &HC2AD% ' Fiter=Digital; Recover Mode=Auto; Quality Threshold=4; Recovery Speed=Slow Data &HCA81% ' FIFO INT Level=8; Sync on=2;Fifo Fill Start=Sync; Reset Sensitivity=High; Disable:FIFO Fill Enabled Data &HC483% ' Enable: AFC Mode; AFC; Frequency Offset Register Disable: High Accuracy; Strobe Data &H9820% ' Frequenz Shift=POS; Power Out=0 dB; Deviation=45 khz Data &HE000% ' WakeUp-Timer=0s Data &HC800% ' Duty Cycle = Infinity % OFF Data &HC000% ' Low batterie=2,2V; Clock Pin=1 Mhz Data &HCED4% ' Synchron Pattern Data &HCC76% ' PLL Settings Data &H0000% ' Status lesen, irqs zurückstellen Data 0% ' Ende initialisierung