Program to find the addresses of devices on the 1-wire bus

Assumes the bus is interfaced via a Maxtor DS2482-100 IIC to 1-wire adapter.

It then reads the temperatures from these, assuming all are temperature probes.

Number of devices limited here to 5 - see PROCinit to change that.

Search algorithm and crc calculation are adapted from Maxtor datasheets.

Uses Reporter from Martin Avison to display results.


REM read temperatures

ON ERROR PROCerror
PROCinit
devicecount%=0
PROCgetaddresses(devicecount%)
PRINT "Found ";devicecount%;" devices"'

res%=1:REM 9 bits

REPEAT
  FOR dev%=0 TO devicecount%-1
    A$= "Temp="+STR$ FNget_temp(dev%,res%)+"C"
    PRINT A$
  NEXT
  PRINT
  PROCwait(0.2)
UNTIL FALSE

END
REM ================================

DEF PROCinit
REM debugging
logging%=FALSE
DIM logbuffer% 256
log%=0
DIM debug% 16

REM storage
maxdevices%=5
DIM device_address%(maxdevices%,1)
DIM address% 8*maxdevices%

REM addresses for interface
readaddr%=(&1B<<1) +1
writeaddr%=(&1B<<1)
REM commands for interface
iic_reset%=&F0
iic_setreadptr%=&E1
iic_writeconfig%=&D2
iic_1_wirereset%=&B4
iic_1_wiresinglebit%=&87
iic_1_wirewritebyte%=&A5
iic_1_wirereadbyte%=&96
iic_1_wiretriplet%=&78
REM interface registers
statusreg%=&F0
datareg%=&E1
configreg%=&C3
REM commands for 1-wire bus
matchrom%=&55
skiprom%=&CC
searchrom%=&F0
readscratch%=&BE
readrom%=&33
convert%=&44
writescratch%=&4E
REM
DIM data% 32
DIM errblock% 256
DIM ROM_NO(8)
STATUS_1WB = 1
STATUS_TSB = &40
STATUS_SBR = &20
STATUS_DIR = &80
STATUS_PPD = 2
PROCfillcrctab
ENDPROC

DEF FNget_temp(devno%,resolution%)
PROCwritebyte(iic_reset%)
IF NOT(FNOWreset) THEN ERROR 1,"FAILED RESET"
PROCmatchrom(devno%)
PROCwritebyte(convert%)
IF FNOWreset
PROCmatchrom(devno%)
PROCwritebyte(readscratch%)
crc8%=0
FOR I%=0 TO8
  PROCreadbyte
  D%=?data%
  debug%?I%=D%
  crc8%=FNdocrc8(D%)
  IF I%=0 THEN tl%=D%
  IF I%=1 THEN th%=D%
NEXT
IF crc8%<>0 THEN
  FORJ%=0TO8
    PRINT "&";~(debug%?J%);" ";
  NEXT
  PRINT '"crc mismatch reading temp: crc=&"+STR$~crc8% :END
ENDIF
temp=FNshowtemp(th%,tl%,resolution%)
=temp

DEF PROCreadbyte
LOCAL return%
data%?0=iic_1_wirereadbyte%
SYS "XIIC_Control",writeaddr%,data%,1 TO errblock%;flags%
PROCcheckstatus
?(data%+0)=iic_setreadptr%
?(data%+1)=datareg%
SYS "XIIC_Control",writeaddr%,data%,2 TO errblock%;flags%
PROCcheckstatus
SYS "XIIC_Control",readaddr%,data%,8 TO errblock%;flags%
return%=?data%
PROCcheckstatus
PROCwritelog("ReadTempLog","readbyte=&"+STR$~(return%))
data%?0=return%
ENDPROC

DEF FNshowtemp(th%,tl%,places%)
LOCAL I%,J%,temp,mask%,nflag%
IF places%<1 THEN places%=1
IF places%>4 THEN places%=4
CASE places% OF
  WHEN 1:mask%=&FFF8
  WHEN 2:mask%=&FFFC
  WHEN 3:mask%=&FFFE
  WHEN 4:mask%=&FFFF
ENDCASE
I%=(th%<<8) + tl%
I% = I%AND mask%
IF (I%AND&F000) <>0 THEN I%=((-I%) AND &FFF):nflag%=TRUE
temp=I%/16
IF nflag% THEN temp=-temp
=temp

DEF PROCcheckstatus
LOCAL S%
IF flags%AND1 THEN
  *REPORTSTACK
  *report ~(errblock%!0)
  END
ENDIF
REPEAT
  S%=FNreadreg
UNTIL NOT(S% AND STATUS_1WB)
ENDPROC

DEF PROCmatchrom(devno%)
LOCAL offset%
offset%=8*devno%
offset%=address%+offset%
REM *REPORT address% devno% offset%
data%?0 = iic_1_wirewritebyte%
data%?1 = matchrom%
SYS "XIIC_Control",writeaddr%,data%,2 TO errblock%;flags%
PROCcheckstatus
FOR N% = offset% TO offset% + 7 STEP 1
  PROCwritebyte(?N%)
NEXT
PROCwritelog("ReadTempLog","matchrom sending &"+STR$~(?N%)+" from &"+STR$ N%)
PROCcheckstatus
ENDPROC


DEF PROCgetaddresses(RETURN devno%)
ROM_NO()=0

REPEAT
  IF devno%=0 THEN
    SUCCESS%=FNOWfirst
  ELSE
    SUCCESS%=FNOWnext
  ENDIF
  PROCcopyaddress(devno%)
  ptr%=address% + 8*devno%
  FOR I%=0 TO3
    ?(ptr%+I%)= ( device_address%(devno%,0) >> (I%*8) ) AND &FF
  NEXT
  ptr% += 4
  FOR I%=0 TO3
    ?(ptr%+I%)= ( device_address%(devno%,1) >> (I%*8) ) AND &FF
  NEXT

  devno%+=1
UNTIL (NOT(SUCCESS%)) OR (LastDeviceFlag) OR (devno%>maxdevices%)

ENDPROC

DEF FNshowstat(byte%)
LOCAL A$,I%
A$=STR$~byte% + ": "
FOR I%=0 TO7
  IF (byte% AND (1<0 THEN
    CASE I% OF
    WHEN 0:A$+= "1 Wire Busy, "
    WHEN 1:A$+= "Presence Pulse Detected, "
    WHEN 2:A$+= "Short Detected, "
    WHEN 3:A$+= "Logic Level=1, "
    WHEN 4:A$+= "Reset done, "
    WHEN 5:A$+= "Single Bit Result, "
    WHEN 6:A$+= "Triplet Second Bit, "
    WHEN 7:A$+= "Branch Direction Taken"
    ENDCASE
  ENDIF
NEXT
=A$

DEF PROCwritescratchpad(alarmhi%,alarmlow%,config%)
PROCwritebyte(writescratch%)
PROCwritebyte(alarmhi%)
PROCwritebyte(alarmlow%)
PROCwritebyte(config%)
ENDPROC


DEF FNreadreg
SYS "XIIC_Control",readaddr%,data%,4 TO errblock%;flags%
IF (flags%AND1)<>0 THEN
   *REPORT readreg error returned ~(errblock%!0)
ENDIF
=?data%

DEF PROCtriplet(dir%)
?(data%+0)=iic_1_wiretriplet%
?(data%+1)=dir%
SYS "XIIC_Control",writeaddr%,data%,2 TO errblock%;flags%
PROCcheckstatus
PROCwritelog("ReadTempLog","triplet")
ENDPROC

DEF PROCwaitready
LOCAL S%
REPEAT
  S%=FNreadreg
UNTIL NOT(S% AND STATUS_1WB)
ENDPROC

DEF PROCwritebyte(byte%)
?(data%+0)=iic_1_wirewritebyte%
?(data%+1)=byte%
SYS "XIIC_Control",writeaddr%,data%,2 TO errblock%;flags%
PROCcheckstatus
PROCwritelog("ReadTempLog",FNshowcmd(byte%))
ENDPROC

DEF PROCsetreadptr(reg%)
?(data%+0)=iic_setreadptr%
?(data%+1)=reg%
SYS "XIIC_Control",writeaddr%,data%,2 TO errblock%;flags%
PROCcheckstatus
PROCwritelog("ReadTempLog","setreadptr")
ENDPROC

DEF PROCwait(secs)
  IF INKEY(100*secs)
ENDPROC

DEF PROCcopyaddress(dev%)
LOCAL I%, ptr%, shift%
device_address%(dev%,0)=0
device_address%(dev%,1)=0
FOR I%=0 TO7
  ptr%=I%DIV4
  shift%=(I%MOD4)*8
  value%=ROM_NO(I%)AND&FF
  address%!(I%+8*dev%)=value%
  device_address%(dev%,ptr%) = device_address%(dev%,ptr%) OR (value% << shift%)
NEXT
ENDPROC

DEF FNOWreset
LOCAL status
?(data%+0)=iic_1_wirereset%
SYS "XIIC_Control",writeaddr%,data%,1 TO errblock%;flags%
PROCcheckstatus
status=FNreadreg
PROCwait(0.02)
PROCwritelog("ReadTempLog","OWreset")
=( (status AND STATUS_PPD) = STATUS_PPD)

DEF FNOWfirst
REM    // reset the search state
LastDiscrepancy = 0
LastDeviceFlag = FALSE
LastFamilyDiscrepancy = 0
=FNOWsearch

DEF FNOWnext
=FNOWsearch

DEF FNOWsearch
ROM_NO()=0
id_bit_number = 1
last_zero = 0
rom_byte_number = 0
rom_byte_mask = 1
search_result = FALSE
crc8% = 0
IF NOT(LastDeviceFlag) THEN
  IF NOT(FNOWreset) THEN
    LastDiscrepancy = 0
    LastDeviceFlag = FALSE
    LastFamilyDiscrepancy = 0
    =FALSE
  ENDIF
  PROCwaitready
  PROCwritebyte(&F0)
  PROCwaitready
  PROCsearchloop
  IF (NOT (  (id_bit_number <65) OR (crc8% <>0) ) )  THEN
    LastDiscrepancy = last_zero
    IF (LastDiscrepancy = 0) THEN
      LastDeviceFlag = TRUE
    ENDIF
    search_result = TRUE
  ENDIF
IF (NOT(search_result) OR ( (ROM_NO(0) AND &FF ) = 0)) THEN
  LastDiscrepancy = 0
  LastDeviceFlag = FALSE
  LastFamilyDiscrepancy = 0
  search_result = FALSE
ENDIF
=search_result

DEF PROCsearchloop
pass%=0
REPEAT
  pass%+=1
  IF (id_bit_number < LastDiscrepancy) THEN
    IF ((ROM_NO(rom_byte_number)  AND  rom_byte_mask) > 0) THEN
      search_direction = 1
    ELSE
      search_direction = 0
    ENDIF
  ELSE
    IF (id_bit_number = LastDiscrepancy) THEN
      search_direction = 1
    ELSE
      search_direction = 0
    ENDIF
  ENDIF
  status = FN_DS2482_search_triplet(search_direction)
  id_bit = ( (status  AND  STATUS_SBR) = STATUS_SBR )
  cmp_id_bit = ( (status  AND  STATUS_TSB) = STATUS_TSB )
  IF  ((status  AND  STATUS_DIR)<>0) THEN
    search_direction = 1
  ELSE
    search_direction = 0
  ENDIF
  IF ((id_bit)  AND  (cmp_id_bit)) THEN
    ENDPROC
  ELSE
    IF ((NOTid_bit)  AND  (NOTcmp_id_bit)  AND  (search_direction = 0)) THEN
      last_zero = id_bit_number
      IF (last_zero < 9) THEN
        LastFamilyDiscrepancy = last_zero
      ENDIF
    ENDIF
    IF (search_direction = 1) THEN
      ROM_NO(rom_byte_number) = rom_byte_mask OR ROM_NO(rom_byte_number)
    ELSE
      ROM_NO(rom_byte_number) = (NOT(rom_byte_mask)) AND ROM_NO(rom_byte_number)
    ENDIF
    id_bit_number += 1
    rom_byte_mask = ( ( rom_byte_mask << 1 ) AND &FF )
    IF (rom_byte_mask = 0) THEN
      crc8%=FNdocrc8( ROM_NO(rom_byte_number) )
      rom_byte_number += 1
      rom_byte_mask = 1
    ENDIF
  ENDIF
UNTIL (rom_byte_number >= 8)
ENDPROC

DEF FN_DS2482_search_triplet(search_direction)
LOCAL status, poll_count, POLL_LIMIT,dir%
POLL_LIMIT=100
IF (search_direction) THEN dir%=&80 ELSE dir%=0
PROCtriplet(dir%)
REPEAT
status=FNreadreg
  poll_count +=1
UNTIL ( (status AND STATUS_1WB) =0 ) OR (poll_count > POLL_LIMIT)
IF (poll_count >= POLL_LIMIT) THEN
  ERROR 1,"Read failed"
ENDIF
=status

DEF FNdocrc8(value)
LOCAL ptr%,crc
ptr%=(crc8% EOR value) AND &FF
crc=crctab%(ptr%)
PROCwritelog("ReadTempLog","crc=&"+STR$~crc)
=crc

DEF PROCfillcrctab
LOCAL I%
DIM crctab%(255)
REM static unsigned char dscrc_table[] = {
DATA 0, 94,188,226, 97, 63,221,131,194,156,126, 32,163,253, 31, 65
DATA 157,195, 33,127,252,162, 64, 30, 95, 1,227,189, 62, 96,130,220
DATA 35,125,159,193, 66, 28,254,160,225,191, 93, 3,128,222, 60, 98
DATA 190,224, 2, 92,223,129, 99, 61,124, 34,192,158, 29, 67,161,255
DATA 70, 24,250,164, 39,121,155,197,132,218, 56,102,229,187, 89, 7
DATA 219,133,103, 57,186,228, 6, 88, 25, 71,165,251,120, 38,196,154
DATA 101, 59,217,135, 4, 90,184,230,167,249, 27, 69,198,152,122, 36
DATA 248,166, 68, 26,153,199, 37,123, 58,100,134,216, 91, 5,231,185
DATA 140,210, 48,110,237,179, 81, 15, 78, 16,242,172, 47,113,147,205
DATA 17, 79,173,243,112, 46,204,146,211,141,111, 49,178,236, 14, 80
DATA 175,241, 19, 77,206,144,114, 44,109, 51,209,143, 12, 82,176,238
DATA 50,108,142,208, 83, 13,239,177,240,174, 76, 18,145,207, 45,115
DATA 202,148,118, 40,171,245, 23, 73, 8, 86,180,234,105, 55,213,139
DATA 87, 9,235,181, 54,104,138,212,149,203, 41,119,244,170, 72, 22
DATA 233,183, 85, 11,136,214, 52,106, 43,117,151,201, 74, 20,246,168
DATA 116, 42,200,150, 21, 75,169,247,182,232, 10, 84,215,137,107, 53
FOR I%=0 TO255
  READ crctab%(I%)
NEXT
ENDPROC

DEF PROCerror
  ON ERROR OFF
   *REPORTERROR
   PRINT REPORT$ + " at line " + STR$ ERL
   IF log%<>0 THEN CLOSE#log%:log%=0
  END
ENDPROC

DEF FNshowcmd(byte%)
LOCAL A%
CASE byte% OF
  WHEN &55: A$="matchrom"
  WHEN &CC: A$="skiprom"
  WHEN &F0: A$="searchrom"
  WHEN &BE: A$="readscratch"
  WHEN &33: A$="readrom"
  WHEN &44: A$="convert"
  WHEN &4E: A$="writescratch"
OTHERWISE A$="&"+STR$~byte%
ENDCASE
=A$


DEF FNramfree(buf%)
LOCAL space%
$buf%="RamDisc0"+CHR$(0)
SYS "RamFS_FreeSpace",buf% TO space%
=space%

REM ................... WRITE LOG FILES

Check free space on ram disc
File should not grow to more than 25% of free space
When it does, delete any log-v1 file
rename log as log_v1
start new log

DEF PROCwritelog(logname$,message$)
REM IF DEBUG%AND1 THEN *reportstack
IF NOT(logging%) THEN
REM  PRINT message$
  ENDPROC
ENDIF
LOCAL log$,logsize%,freespace%
log$="RAM::RAMDISC0.$." + logname$
$logbuffer%=log$+CHR$(0)
log%=OPENIN(log$)
IF log%<>0 THEN
  SYS "OS_File",17,logbuffer% TO ,,,,logsize%
  freespace%=FNramfree(logbuffer%)
  REM  *REPORT WL: commonwritelog: log$ ~logsize% ~freespace%
  IF logsize%>(freespace%/4) THEN
    log%=OPENIN(log$ + "_v1")
    IF log%<>0 THEN
      CLOSE#log%:log%=0
      OSCLI("*DELETE " + log$+"_v1")
    ENDIF
    OSCLI("*RENAME " + log$ + " " + log$ + "_V1")
  ENDIF
  CLOSE#log%:log%=0
ENDIF
log%=OPENUP(log$)
IF log%=0 THEN
  log%=OPENOUT(log$)
  IF log%=0 THEN ERROR 1,"Cannot create "+log$
  OSCLI("SETTYPE " + log$ + " text")
ELSE
  PTR#log%=EXT#log%
ENDIF
BPUT#log%,message$ + CHR$(13)
CLOSE#log%:log%=0
ENDPROC