;-------------------------------------------------------------------------------
; 16F88
; interne oscillator op 8MHz
; interne MCLR
;-------------------------------------------------------------------------------
include 16f88

pragma target OSC       INTOSC_NOCLKOUT   -- HS crystal or resonator
pragma target clock     8_000_000         -- oscillator frequency
pragma target WDT       disabled          -- no watchdog
pragma target LVP       disabled          -- no low-voltage programming
pragma target CCP1MUX   pin_B3            -- ccp1 pin on B3
pragma target MCLR      internal          -- reset internally
OSCCON_IRCF = 7                           -- set prescaler to 1 (8 MHz)

enable_digital_io()    ;alle pinnen digitale IO

;LED is via voorschakelweerstand aangesloten op pin B7
alias   led      is pin_B7
pin_B7_direction =  output
led = off

alias   Motorola is pin_B0
pin_B0_direction =  input

alias   Switch is pin_A5
pin_A5_direction =  input

;-------------------------------------------------------------------------------
;instellingen voor Timer0
;-------------------------------------------------------------------------------
INTCON_TMR0IE   = high  ;interrupt
OPTION_REG_T0CS = low   ;Timer0 timer mode
OPTION_REG_PSA  = low   ;prescaler op Timer0
;de prescaler op 1/4
OPTION_REG_PS = 0b001
TMR0          = 0

;-------------------------------------------------------------------------------
;LCD declaratie en initialisatie
;-------------------------------------------------------------------------------
;Volgende constanten moeten gedeclareerd worden:
const byte LCD_ROWS     = 2               -- 1, 2 or 4 lines
const byte LCD_CHARS    = 16              -- 8, 16 or 20 chars per line
;Alisassen voor de handshake-lijnen:
alias   lcd_rs          is  pin_A4        -- cmd/data select
alias   lcd_en          is  pin_A6        -- trigger
pin_A4_direction       = output
pin_A6_direction       = output
;Aliassen voor de vier datalijnen:
alias lcd_dataport  is  portA_low         -- 4 databits
pin_A0_direction       = output
pin_A1_direction       = output
pin_A2_direction       = output
pin_A3_direction       = output

;laad de eigenlijke bibliotheek
include lcd_hd44780_4
;en initialiseer het display
lcd_init()                            -- init the lcd controller
;de printbibliotheek
include print

;wis het scherm
lcd_clear_screen()

;Het kloppend hart van de decoder
include MMInterrupt

;De marklin adres lookuptabel
include MMLookup

;-------------------------------------------------------------------------------
;PROG variabelen
;-------------------------------------------------------------------------------
var byte*3 dwRawData = 0
var byte RawData[3] at dwRawData
var byte DataLow
var byte DataMid
var byte DataAddr

var byte Temp
var word wSwitchAdres

;LCD strings
const byte RED[3]    = "Red"
const byte GREEN[3]  = "Grn"
const byte SW_ON[3]  = "ON "
const byte SW_OFF[3] = "OFF"

;-------------------------------------------------------------------------------
T2CON_TMR2ON = high    ;turn timer2 on;
INTCON_GIE = high      ;enable interrupts
;-------------------------------------------------------------------------------
forever loop
  if(DataStatus > DATA_NONE)then
    ;Er is data, de led mag uit
    Led = off
    ;schuif data door zodat de interruptvariabele terug 'vrij' komt om
    ;terug aangepast te worden door de interruptroutine
    dwRawData = dwMMPassData
    ;Verdeel de data:
    ;DataLow bevat de 'ruwe' data
    ;bij seindata is dit de schakeldata (subadres + schakelstatus)
    DataLow = RawData[0]
    ;DataMid heeft bij seindata geen zin (is steeds 0)
    DataMid = RawData[1] & 0x03
    ;DataAddr bevat het adres (eerst van 18 bits 24 bits maken om eenvoudiger
    ;te kunnen bewerken)
    dwRawData = dwRawData << 6
    DataAddr = RawData[2]

    ;enkel wisseldata interesseert ons voor het ogenblik
    if(DataStatus == DATA_TURNOUT)then
      ;seindata

      ;Op het display geven we op de bovenste regel de 'ruwe' data
      ;Ruw - Adres - Subadres - schakelstatus
      lcd_cursor_position(0,0)
      print_byte_hex(lcd, MMPassData[2])
      print_byte_hex(lcd, MMPassData[1])
      print_byte_hex(lcd, MMPassData[0])
      _lcd_write_data("-")
      ;Adres
      print_byte_hex(lcd, DataAddr)
      _lcd_write_data("-")
      ;SubAdres
      print_byte_hex(lcd, (DataLow & 0xFC))
      _lcd_write_data("-")
      ;Schakelstatus
      print_byte_hex(lcd, (DataLow & 0x03))

      ;Op de tweede regel zetten we 'leesbare' data
      ;Schakeladres - Rood/groen - Schakelstatus

      ;bereken het decimaal adres
      wSwitchAdres =  MMAdresLookup[DataAddr]
      ;wSwitchAdres - 1    * 4
      wSwitchAdres = (wSwitchAdres - 1) << 2
      ;bereken de individuele schakelaar
      Temp = (DataLow & 0xFC)
      case Temp of
        0x00 : wSwitchAdres = wSwitchAdres + 1
        0xC0 : wSwitchAdres = wSwitchAdres + 1
        0x30 : wSwitchAdres = wSwitchAdres + 2
        0xF0 : wSwitchAdres = wSwitchAdres + 2
        0x0C : wSwitchAdres = wSwitchAdres + 3
        0xCC : wSwitchAdres = wSwitchAdres + 3
        0x3C : wSwitchAdres = wSwitchAdres + 4
        0xFC : wSwitchAdres = wSwitchAdres + 4
      end case
      lcd_cursor_position(1,0)
      ;Adres
      print_byte_dec(lcd, wSwitchAdres)
      _lcd_write_data(" ")
      _lcd_write_data("-")
      _lcd_write_data(" ")
      ;Kleur schakelaar
      Temp = DataLow & 0xC0
      if(Temp == 0)then
        print_string(lcd, RED)
      else
        print_string(lcd, GREEN)
      end if
      _lcd_write_data(" ")
      _lcd_write_data("-")
      _lcd_write_data(" ")
      ;Status
      Temp = DataLow & 0x03
      if(Temp == 0)then
        print_string(lcd, SW_OFF)
      else
        print_string(lcd, SW_ON)
      end if
      _lcd_write_data(" ")
      _lcd_write_data(" ")
      _lcd_write_data(" ")
    end if
    ;data verwerkt
    DataStatus = DATA_NONE
  end if
  
  ;T0 afgegaan?
  if(T0Passed != 0)then
    T0Passed = 0
    BlinkTimer = BlinkTimer - 1
    if(BlinkTimer == 0)then
      BlinkTimer = BLINKTIME
      ;knipper de led om aan te tonen dat er geen MM signaal is!
      Led = !Led
    end if
  end if
end loop
;-------------------------------------------------------------------------------