'*******************************************************************************
'************************* 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