;-------------------------------------------------------------------------------
;MMInterrupt
;-------------------------------------------------------------------------------
;-------------------------------------------------------------------------------
;Interrupt B0 instellingen
;-------------------------------------------------------------------------------
OPTION_REG_INTEDG = high
INTCON_INTE = high
;-------------------------------------------------------------------------------
;INT variabelen
;-------------------------------------------------------------------------------
const byte WAIT = 5
var volatile byte WaitLoop = WAIT
var volatile byte*3 dwMMData = 0
var volatile byte MMData[3] at dwMMData
var volatile byte MMDataLow at MMData[0]
var volatile byte MMDataMid at MMData[1]
var volatile byte MMDataHigh at MMData[2]
var volatile byte*3 dwOldMMData = 0
var volatile byte OldMMData[3] at dwOldMMData
var volatile byte OldMMDataLow at OldMMData[0]
var volatile byte OldMMDataMid at OldMMData[1]
var volatile byte OldMMDataHigh at OldMMData[2]
var volatile byte*3 dwMMPassData = 0
var volatile byte MMPassData[3] at dwMMPassData
var volatile byte MMPassDataLow at MMPassData[0]
var volatile byte MMPassDataMid at MMPassData[1]
var volatile byte MMPassDataHigh at MMPassData[2]
const byte BITCOUNT = 18
var volatile byte BitCounter = BITCOUNT
var volatile byte ITemp
var volatile byte CommandStatus
const byte COMMANDSTATUS_NONE = 0x00
const byte COMMANDSTATUS_PAUSE = 0x01
const byte COMMANDSTATUS_DATABUSY = 0x11
const byte COMMANDSTATUS_COMPLETE = 0x80
const byte DATA_NONE = 0x00
const byte DATA_LOCO = 0x01
const byte DATA_TURNOUT = 0x02
var volatile byte DataStatus = DATA_NONE
const byte TIME_TURNOUT = 60
var volatile byte DataTime
var volatile byte T0Passed = 0
const byte BLINKTIME = 250
var byte BlinkTimer = BLINKTIME
;-------------------------------------------------------------------------------
;INTERRUPT PROCEDURE
;-------------------------------------------------------------------------------
procedure Interrupt is
pragma interrupt
;tot hiertoe zij 12 instructies verlopen vanaf het moment dat de interrupt
;actief werd. 12 * 1/(8000000 / 4) = 6µs
;Bij een logische nul blijft het signaal 13µs hoog bij een seindecoder
;of 26µs voor een locdecoder.
;Na 27µs bekijken we het signaal: is dit nog hoog hebben we een logische
;één, is det laag hebben we een logische nul.
;pin_B5 = on
if(INTCON_INTF)then
INTCON_INTF = low
;sla de verstreken tijd op
DataTime = TMR0
;reset Timer0
TMR0 = 0
INTCON_TMR0IF = low
;14 instructies = 7µs
if(CommandStatus < COMMANDSTATUS_COMPLETE)then
;data moet nog beginnen of is reeds bezig
CommandStatus = COMMANDSTATUS_DATABUSY
;terug 3µs
;De loop duurt 2,5µs - 5 keer deze loop + voorgaande en één sprong
;geeft 5 * 2.5µs = 12.5µs
;+ 6µs + 7µs + 3µs + 1µs = 29.5µs
while(Waitloop != 0)loop
WaitLoop = WaitLoop - 1
end loop
;verwerk de data - kijk nu naar het signaal
;schuif het ganse datapakket 1 bit naar links
;Een nul wordt automatisch bijgevoegd; een één moeten we controleren
dwMMData = dwMMData << 1
if(Motorola)then
MMDataLow = MMDataLow | 1
end if
BitCounter = BitCounter - 1
if(BitCounter == 0)then
;alle 18 bits zijn binnen
CommandStatus = COMMANDSTATUS_COMPLETE
DataStatus = DATA_NONE
;Data gelijk?
if(dwMMData == dwOldMMData)then
;data is identiek aan de vorige, we hebben een geldig commando
dwOldMMData = 0
;afhankelijk van de polariteit van het signaal kan het
;nog zijn dat de volledige data geïnverteerd moet worden
if(OPTION_REG_INTEDG == low)then
;negatief signaal: inverteren
MMData[0] = !MMData[0]
MMData[1] = !MMData[1]
MMData[2] = !MMData[2]
end if
;enkele 'addertjes onder het gras'...
;de data 0x3FFFF komt overeen met een DCC idle signaal
;en mag niet verwerkt worden
if(dwMMData != 0x3FFFF)then
;De IB stuurt ook 'onmogelijke' data 0x02A800 als
;idle-signaal. Ook filteren
if(dwMMData != 0x02A800)then
;data doorgeven
dwMMPassData = dwMMData
if(DataTime > TIME_TURNOUT)then
DataStatus = DATA_LOCO
else
;Nog een eigenaardigheid van de IB: een lok-commando in oud-motorola
;formaat wordt na het aanduiden van de lok éénmalig als seindata
;verzonden. De vijfde trit die normaal bij seindata altijd nul is,
;wordt als onderscheid dan als één verzonden. - filteren!
if((MMDataMid & 0x03) == 0)then
DataStatus = DATA_TURNOUT
end if
end if
end if
end if
else
;data verschillend, fout is eerste keer dat commando verzonden wordt
dwOldMMData = dwMMData
end if
dwMMData = 0
BitCounter = BITCOUNT
end if
end if
WaitLoop = WAIT
end if
if(INTCON_TMR0IF)then
;Positief of negatief signaal?
if(Motorola)then
;pause is hoog, int op lage flank
OPTION_REG_INTEDG = low
else
;pause is laag, int op hoge flank
OPTION_REG_INTEDG = high
end if
;zaten we al in een pauze?
if(CommandStatus != COMMANDSTATUS_PAUSE)then
;was er nog niet complete data? - Afbreken!
dwMMData = 0
BitCounter = BITCOUNT
CommandStatus = COMMANDSTATUS_PAUSE
end if
;meldt dat T0 is afgegaan
T0Passed = 1
INTCON_TMR0IF = low
TMR0 = 0
end if
end procedure
;-------------------------------------------------------------------------------