' program for orienteering control using an iButton (DS1992, DS1993 and up) ' works with PIC16F628 ' maximum number of numbered controls: 31 (DS1992), 127 (DS1993) ... ' maximum number of controls in one iButton: 31 (DS1992), 127 (DS1993) ... ' works by dividing memory in 4 byte blocks - every block is one control written in unix timestamp format ' this design is pretty simple, at the cost of smaller number of controls program Kutijica ' ibutton input ports for version ROUND BOX 'symbol REDLED=1 ' LED flash 'symbol BUZZ=2 ' piezo buzzer 'symbol IBUTTPIN=4 ' ibutton socket ' ### NOTE VERSION RED-LED ### ' ibutton input ports for version HAMMOND BOX symbol REDLED=0 '0 pin 17 for version 2, '1 pin 18 for version 1 symbol BUZZ=3 ' piezo buzzer symbol IBUTTPIN=2 ' ' ' General symbol LEDON=0 ' pull-down for on symbol LEDOFF=1 ' controlID - maximum number is 31 (DS1992), 127 (DS1993) ... dim js as byte[8] dim js1 as byte[8] dim js2 as byte[8] dim counter as byte dim sec as longword dim tim as byte dim crcTest as byte dim i as byte dim idBox as byte ' read from dip switch dim idBoxLoc as word dim wasConnected as boolean dim clockSet as byte 'read some memory sub procedure Ow_Read_Serial(dim byref PORT as byte, dim pin as byte, dim byref out as byte[8], dim leng as byte) dim i as byte dim tmpRead as byte i = 0 while i < leng ' we will move 8 bytes tmpRead = ow_read(PORT,PIN) ' get one byte from Dallas iButton out[i] = tmpRead ' move the byte into array inc(i) ' next i wend end sub '======================================================= 'CRC8 without table 'All you have to do is to initialise the crc variable (to zero or $FFFF) ' and then call the procedure for every byte of your data. '======================================================= sub procedure ByteCRC(dim byref CRC as byte,dim CRCData as byte) dim i,TstBit as byte For i = 0 to 7 ' Do for all 8 bits in data byte TstBit = CRC xor CRCData 'CRC.0 xor CRCData.0 ' XOR bit0 of data byte and crc TstBit = TestBit(TstBit,0) CRCData = CRCData >> 1 ' Position data byte for next bit test If TstBit = 1 then ' If test bit not set, just shift CRC CRC = CRC xor $18 ' If set, account for EXOR feedback end if ' Shift right the CRC byte CRC = CRC >> 1 ' CRC bit 0 to bit bucket CRC.7 = TstBit ' Test bit rotates into CRC bit 7 Next i end sub ' set the PIC clock to real time sub procedure readTimeFromButton() dim numOfTries as byte dim tempSec as longword numOfTries=0 do inc(numOfTries) ow_reset(PORTA,IBUTTPIN) ' onewire reset signal ow_write(PORTA,IBUTTPIN,$CC) ' write skip read ROM ow_write(PORTA,IBUTTPIN,$66) ' write to Scratch pad Ow_Read_Serial(PORTA,IBUTTPIN,js,5) if ((js[4]>$49) and (js[4]<$FF)) then ' time must be between october 2008 and 2037 (or even 2105 if unsigned) sec = ((((js[4] << 8) or js[3])<<8) or js[2] ) <<8 or js[1] ' set time counter=0 clockSet = 6 ' flash green LED, on the minute for 5 minutes PORTA.REDLED = LEDON delay_ms(50) PORTA.REDLED = LEDOFF delay_ms(250) end if ' loop until seconds are over October 2008 and it's equal to the stuff read from the chip OR the number of tries is over 200 loop until (((sec>1224736768) and (sec = ((((js[4] << 8) or js[3])<<8) or js[2] ) <<8 or js[1])) or numOfTries>200) end sub ' write time to button sub procedure writeTimeToButton(dim location as word) dim currentTime as longword dim firstWriteOK as byte firstWriteOK=0 if (location>=0) then ' (this statement is redundant) ' save current time currentTime=sec do ow_reset(PORTA,IBUTTPIN) ' onewire reset signal ow_write(PORTA,IBUTTPIN,$CC) ' write skip read ROM ow_write(PORTA,IBUTTPIN,$0F) ' write to Scratch pad ow_write(PORTA,IBUTTPIN,Lo(location)) ' write location lower byte ow_write(PORTA,IBUTTPIN,Hi(location)) ' write location higher byte ow_write(PORTA,IBUTTPIN,Highest( currentTime )) ' write time (highest byte) ow_write(PORTA,IBUTTPIN,Higher( currentTime )) ' write time (evem more higher byte) ow_write(PORTA,IBUTTPIN,Hi( currentTime )) ' write time (higher byte) ow_write(PORTA,IBUTTPIN,Lo( currentTime )) ' write time (lower byte) delay_us(200) 'delay, needed to work ow_reset(PORTA,IBUTTPIN) ' onewire reset signal ow_write(PORTA,IBUTTPIN,$CC) ' skip ROM ow_write(PORTA,IBUTTPIN,$AA) ' read scratchpad Ow_Read_Serial(PORTA,IBUTTPIN,js,7) delay_us(200) ' check if scratchpad is correct if (js[0]=Lo(location)) and (js[1]=Hi(location)) then ow_reset(PORTA,IBUTTPIN) ' onewire reset signal ow_write(PORTA,IBUTTPIN,$CC) ' skip ROM ow_write(PORTA,IBUTTPIN,$55) ' copy to memory ow_write(PORTA,IBUTTPIN,js[0]) ' write location ow_write(PORTA,IBUTTPIN,js[1]) ' - I I - ow_write(PORTA,IBUTTPIN,js[2]) ' write extra control byte delay_us(200) ow_reset(PORTA,IBUTTPIN) ' onewire reset signal ow_write(PORTA,IBUTTPIN,$CC) ' skip ROM ow_write(PORTA,IBUTTPIN,$F0) ' read from memory ow_write(PORTA,IBUTTPIN,Lo(location))' set location from where to read ow_write(PORTA,IBUTTPIN,Hi(location)) delay_us(100) Ow_Read_Serial(PORTA,IBUTTPIN,js,4) ' read 4 bytes of data from memory if ((js[3] = Lo(currentTime)) and (js[2] = Hi (currentTime)) and (js[1] = Higher(currentTime)) and (js[0] = Highest (currentTime))) then firstWriteOK=1 end if end if ' loop until time is correctly written loop until ( firstWriteOK=1 ) or (currentTime+2 1) then ' flash red LED on the minute if (sec mod 60 = 0) then PORTA.REDLED = LEDON dec(clockSet) end if end if if ((sec + idBox) mod 300 = 0) then ' quiet beep every 5 mins PORTA.BUZZ=1 delay_ms(10) ' 10 works best PORTA.BUZZ=0 end if if (clockSet = 0) then ' warning that clock is not set PORTA.REDLED = LEDON delay_ms(50) PORTA.REDLED = LEDOFF PORTA.BUZZ=1 delay_ms(100) PORTA.BUZZ=0 end if end if end sub main: TRISA = 0 ' porta is output (except RA1) PORTA = 0 ' initialize porta TRISB = $FF ' portb is input OPTION_REG.NOT_RBPU=0 ' enable individual pull-up CMCON = 7 ' Disable Comparators counter = 0 ' Initialize counter sec=0 tim=0 clockSet = 0 T1CON = $31 ' start the timer PIR1.TMR1IF = 0 ' clear TMR1IF PIE1 = 1 ' enable TMR1 interrupts INTCON = $C0 ' Enable global TMR interrupt ' read DIP for idBox idbox = PORTB idBox = idBox xor $FF ' invert bits idBoxLoc=idBox*4 OPTION_REG.NOT_RBPU=1 ' disable individual pull-up _loop: ' first, we read iButton if present ow_reset(PORTA,IBUTTPIN) ' onewire reset signal ow_write(PORTA,IBUTTPIN,$33) ' read iButton - read ROM Ow_Read_Serial(PORTA,IBUTTPIN, js,8) ' read 8 bytes of Dallas iButton crcTest=0 for i=0 to 6 ByteCRC(crcTest,js[i]) next i ' check if iButton present if (((js[0] and js[1] and js[3] and js[4] and js[5] and js[6] and js[7])<>$FF) and (crcTest <> $FF) and (crcTest<>$00) and crcTest=js[7]) then ' iButton is not present if wasConnected=0 then ' ibutton present, check if multiple writing if js[0]=$24 then readTimeFromButton() ' read time from button else writeTimeToButton(idBoxLoc) ' normal button - write current time to button end if end if ' ibutton is not present else ' it was already wasConnected and now is disconnected (wasConnected=0) wasConnected=0 end if if wasConnected=1 then ' flash red led PORTA.REDLED=LEDON delay_ms(30) PORTA.REDLED=LEDOFF delay_ms(30) PORTA.BUZZ=1 delay_ms(200) PORTA.BUZZ=0 delay_ms(200) end if goto _loop end.