'#################################################################################################################################
'#
'#  MiniLogger.bas          Copyright Chris Benndorf/Thomas Marx
'#
'#  Betriebsprogramm fuer den in RC-Line diskutierten MiniLogger
'#  http://www.ganzfix.de/MiniLogger
'#
'#################################################################################################################################

'#################################################################################################################################
'#
'#  Die folgenden Konstanten dienen zur Anpassung an die verwendete Hardware
'#
'#################################################################################################################################

Const Binaerout = 1                                         'Ausgabeformat: 1 = Binaere Daten  /  0 = ASCII-Daten
Const Use_aci_for_rpm = 0                                   'Drehzahl ueber 1 = Comperator Interrupt / 0 = INT0 Interrupt

                                                             ' Falls Use_aci_for_rpm = 0 dann
Const Use_10bit_adc5 = 0                                    'ADC4 mit 10Bit = 1 oder ADC4+5 mit je 8Bit = 0 lesen

Const Minrx = 170                                           'Geberweg des Senders Minimum = 63 / Maximum = 255 / Mitte = 191
Const Use_positiv_ppm = 1                                   'Positives = 1 (z.B. MPX) oder negatives = 0 (z.B. Uralt-Robbe) PPM

Const Eeprom_adress_w = &HA0                                'Basisadresse des verwendeten EEPROMs 24C64A = &HA0 / 24C256 = &HA0
Const Eeprom_adress_r = Eeprom_adress_w + 1                 'Nicht aendern!
Const Eeprom_size = 8192                                    'EEPROM-Groesse in Bytes   24C64A = 8192 / 24C256 = 32768

Const Measured_bytes = 8                                    'Nicht Aendern! Anzahl gemessener Werte pro Datensatz

'#################################################################################################################################
'#
'#  Compiler-Anweisungen
'#
'#################################################################################################################################

$prog , &HF1 , ,                                            'Hardware-Einstellungen fuer internen 1 MHz Taktgeber
$crystal = 1000000                                          '1 MHz, Damit auch die Software davon weiss
$regfile = "at26def.dat"                                    'Wir benutzen einen Tiny26

'#################################################################################################################################
'#
'#  Variablen
'#
'#################################################################################################################################

Dim Subtemp As Word
Dim Eeptr As Word
Dim Icadrsave As Word
Dim Wtimer0 As Word At &H80
Dim Wtimer0lo As Byte At &H80 Overlay
Dim Wtimer0hi As Byte At &H81 Overlay
Dim Wcompare As Word At &H82
Dim Wcomparelo As Byte At &H82 Overlay
Dim Wcomparehi As Byte At &H83 Overlay
Dim Icadr As Word At &H84
Dim Icadrlo As Byte At &H84 Overlay
Dim Icadrhi As Byte At &H85 Overlay
Dim Temp As Word At &H86
Dim Lotemp As Byte At &H86 Overlay
Dim Hitemp As Byte At &H87 Overlay
Dim Collected As Word At &H88
Dim Collectedlo As Word At &H88 Overlay
Dim Collectedhi As Word At &H89 Overlay

'#################################################################################################################################
'#
'#  Hardware initialisieren
'#
'#################################################################################################################################

Ddrb = &B00011000                                           'DDRB  Port 3+4 = Output, alle anderen Input

Config Sda = Portb.0                                        'Ports fuer die I2C-Schnittstelle
Config Scl = Portb.2
I2cinit

Set Portb.4                                                 'LED aus
Set Portb.6                                                 'PullUp f. Drehzahl-Eingang

Config Timer0 = Timer , Prescale = 8                        'Timer0 geht gut
Config Timer1 = Timer                                       'Timer1 braucht noch eine Nachbehandlung
Tccr1b = 4                                                  'DIV/8
Pllcsr = 0

Config Adc = Single , Prescaler = Auto                      'KEINE Angabe von Reference = Internal
Start Adc

'#################################################################################################################################
'#
'#  Interrupt-Quellen
'#
'#################################################################################################################################

On Ovf0 _ovf0 Nosave
Enable Ovf0

#if Use_aci_for_rpm = 1                                     'Thomas' RPM
    Config Aci = On , Trigger = Rising
    On Aci _aci
    Enable Aci
#else                                                       'Chris' RPM
     Config Int0 = Rising
     On Int0 _aci
     Enable Int0
#endif

'#################################################################################################################################
'#
'#  Hauptprogramm
'#
'#################################################################################################################################

Wait 3                                                      'Warten bis alle Servos etc. fertig sind

Icadr = 0                                                   'Neues EEPROM? Alle Bytes auf 0xFF?
Gosub Read_eeprom
If Temp = &HFFFF Then
   Icadr = 0
   Temp = 0
   Gosub Write_eeprom
End If

Gosub Ausgabe                                               'Ausgabe der letzten Messwerte

Enable Interrupts                                           'Interrupts aktivieren

Eeptr = 0                                                   'Schreib-Position fuer Datenlaenge
Collected = 0                                               'Datenmenge
Icadr = 4                                                   'Schreiposition fuer Daten

Do
  Gosub Checkrx                                             'Auf Befehl vom Sender warten...
  While Temp > Minrx                                        'Kanal weit genug aufgedreht?

         Gosub Erfassung                                    'Datensatz lesen und speichern
         Collected = Collected + Measured_bytes             'Datenmenge hochzaehlen

         Gosub Checkrx                                      'Soll weiter aufgezeichnet werden
         If Icadr >= Eeprom_size Then Temp = 0              'und haben wir noch Speicher?
         If Temp < Minrx Then                               'Wenn nicht
            Icadrsave = Icadr                               'Datenptr speichern
            Temp = Collected                                'Datenmenge soll geschrieben werden
            Icadr = Eeptr                                   'Schreibposition der Datenmenge laden
            Gosub Write_eeprom                              'Und im EEPROM ablegen
            Gosub Write_eeprom                              'Zweimal um Fehler abzufangen
            Icadr = Icadrsave                               'Restore des Datenptr
            Eeptr = Icadrsave                               'Naechste Schreibposition
            Temp = 0                                        ' Datenlaenge initialisieren
            Gosub Write_eeprom                              'und speichern
            Gosub Write_eeprom                              'und auch Fehlersicherung speichern
            Collected = 0                                   'Datenmenge wieder auf 0 setzen
            Exit While                                      'und fertig...
         End If
  Wend
Loop Until Icadr >= Eeprom_size
End

'#################################################################################################################################
'#
'#  "Subroutinen"
'#
'#################################################################################################################################

'Sender-Signal pruefen
'-----------------------------------
Checkrx:
#if Use_positiv_ppm = 1
  Bitwait Pinb.5 , Set                                      'Auf positive Flanke warten
  Tcnt1 = 1                                                 'Zaehler starten
  Bitwait Pinb.5 , Reset                                    'Auf negative Flanke warten
  Temp = Tcnt1                                              'Zaehler auslesen
#else
  Bitwait Pinb.5 , Reset                                    'Auf positive Flanke warten
  Tcnt1 = 1                                                 'Zaehler starten
  Bitwait Pinb.5 , Set                                      'Auf negative Flanke warten
  Temp = Tcnt1                                              'Zaehler auslesen
#endif
Return

'Datenausgabe
'-----------------------------------
Ausgabe:
  Open "COMB.3:9600,8,N,1" For Output As #1

  Icadr = 0

  Do

    Gosub Read_eeprom                                       'Datenlaenge auslesen
    Collected = Temp                                        'In die richtige Variable packen
    Gosub Read_eeprom                                       'Vergleichswert lesen
    If Collected <> Temp Then Collected = 0                 'Wenn ungleich, dann ist es ein fehlerhafter datensatz
    If Collected = &HFFFF Then Collected = 0                'Wenn Laenge = 65535, dann ist das EEPROM neu - per Definition! :-)

  #if Binaerout = 0
    Print #1 , Collected
  #else
    Print #1 , Chr(collectedhi) ; Chr(collectedlo);
  #endif

    If Collected = 0 Then Return

    While Collected > 0

        Gosub Read_eeprom
        #if Binaerout = 0
          Print #1 , Temp ;
        #else
          Print #1 , Chr(hitemp) ; Chr(lotemp);
        #endif

        Gosub Read_eeprom
        #if Binaerout = 0
          Print #1 , ";" ; Temp ;
        #else
          Print #1 , Chr(hitemp) ; Chr(lotemp);
        #endif

        Gosub Read_eeprom
        #if Binaerout = 0
          Print #1 , ";" ; Hitemp ; ";" ; Lotemp ; ";";
        #else
          Print #1 , Chr(hitemp) ; Chr(lotemp);
        #endif

        Gosub Read_eeprom
        #if Binaerout = 0                                   '2 freie Bytes fuer zukuenftige Erweiterungen
          Print #1 , ";" ; Hitemp ; ";" ; Lotemp
        #else
          Print #1 , Chr(hitemp) ; Chr(lotemp);
        #endif

        Collected = Collected - Measured_bytes
    Wend

  Loop Until Icadr >= Eeprom_size
Return

'Datenerfassung
'-----------------------------------
Erfassung:
      Reset Portb.4

      Timer0 = 0
      Wtimer0 = 0
      Tifr.tov0 = 1
      Enable Interrupts
      Wcompare = 0
_getrpm_l1:
      If Wtimer0hi.7 = 1 Then Goto _getrpm_l3
      If Wcompare = 0 Then Goto _getrpm_l1
      Wcompare = 0
_getrpm_l2:
      If Wtimer0hi.7 = 1 Then Goto _getrpm_l3
      If Wcompare = 0 Then Goto _getrpm_l2
_getrpm_l3:
      Disable Interrupts

      Temp = Wcompare
      Gosub Write_eeprom                                    'Rotations

      Temp = Getadc(&B11001011)                             'REFS0 + REFS1 + (ADC +0/-1 20x)
      Gosub Write_eeprom

      Temp = Getadc(&B11100010)                             'REFS0 + REFS1 + ADLAR + (PA2/ADC 2)    Battery Voltage
      Temp = Temp And &HFF00
      Subtemp = Getadc(&B11000011)                          'REFS0 + REFS1 + (PA4/ADC 3)    Motor temprature
      Shift Subtemp , Right , 2
      Temp = Temp Or Subtemp
      Gosub Write_eeprom

#if Use_aci_for_rpm = 0
  #if Use_10bit_adc5 = 0
      Temp = Getadc(&B11100100)                             'REFS0 + REFS1 + ADLAR + (PA5/ADC 4) 8Bit Free use
      Temp = Temp And &HFF00
      Subtemp = Getadc(&B11000101)                          'REFS0 + REFS1 + (PA6/ADC 5)  8Bit  Free use
      Shift Subtemp , Right , 2
      Temp = Temp Or Subtemp
      Gosub Write_eeprom
  #else
      Temp = Getadc(&B11000100)                             'REFS0 + REFS1 + PA5/ADC 4   10Bit  Free use
      Gosub Write_eeprom
  #endif
#else
      Temp = Getadc(&B11000100)                             'REFS0 + REFS1 + PA5/ADC 4   10Bit  Free use
      Gosub Write_eeprom
#endif

      Set Portb.4
      Wait 1
Return

'Interrupt-Routinen
'-----------------------------------
_ovf0:
$asm
push zl                                                     '
in zl,SREG                                                  '
push zl                                                     '

lds zl,{Wtimer0hi}                                          ' WTimer0 bildet einen 16Bit-Timer
inc zl                                                      ' High-Byte von WTimer0 wird
sts {Wtimer0hi},zl                                          ' hochgezählt

pop zl
Out Sreg , Zl
pop zl
$end Asm
' Incr Wtimer0hi
Return

'Interrupt-Routinen
'-----------------------------------
_aci:
  Wtimer0lo = Timer0                                        'Version2: Timer0 und WTimer0
  Timer0 = 0                                                ' werden bei Comparator Int
  Wcompare = Wtimer0                                        ' zurückgesetzt
  Wtimer0hi = 0                                             ' 12 Byte kürzer als Version1
Return

'I2C-Routinen
'-----------------------------------

Write_eeprom:
    Disable Interrupts
    I2cstart                                                'start condition
    I2cwbyte Eeprom_adress_w                                'slave address
    I2cwbyte Icadrhi                                        'address of EEPROM
    I2cwbyte Icadrlo                                        'address of EEPROM
    I2cwbyte Hitemp                                         'value to write
    I2cwbyte Lotemp                                         'value to write
    I2cstop                                                 'stop condition
    Enable Interrupts
    Waitms 10                                               'wait for 10 milliseconds
    Incr Icadr
    Incr Icadr
Return

Read_eeprom:
    I2cstart                                                'generate start
    I2cwbyte Eeprom_adress_w                                'slave adsress
    I2cwbyte Icadrhi                                        'address of EEPROM
    I2cwbyte Icadrlo                                        'address of EEPROM
    I2cstart                                                'repeated start
    I2cwbyte Eeprom_adress_r                                'slave address (read)
    I2crbyte Hitemp , Ack                                   'read byte
    I2crbyte Lotemp , Nack                                  'read byte
    I2cstop                                                 'generate stop
    Incr Icadr
    Incr Icadr
Return

'#################################################################################################################################
'#
'#  Initialisierung des internen EEPROMs
'#
'#################################################################################################################################

$eeprom
Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0