Andrew Boyson
/
iot
Backing up an unused program in case of future need
Diff: 1-wire.cpp
- Revision:
- 6:be97d38e0b01
- Parent:
- 5:6226f3c566ef
- Child:
- 7:024ace6d943c
--- a/1-wire.cpp Wed May 11 16:42:35 2016 +0000 +++ b/1-wire.cpp Tue May 31 07:35:28 2016 +0000 @@ -1,13 +1,16 @@ -#include "mbed.h" -#include "log.h" -#include "io.h" +#include "mbed.h" +#include "log.h" +#include "io.h" +#include "1-wire.h" //Bus zone //======== static DigitalInOut pin(p25, PIN_INPUT, PullUp, 0); +static volatile int busvalue; -static int busvalue; +static Timer timer; +static Timer busytimer; //Delays #define ATTACH_US 7 @@ -22,67 +25,32 @@ #define READ_BIT_BUS_LOW_US 6 #define READ_BIT_US 9 #define READ_BIT_RELEASE_US 55 -#define BUS_TIMEOUT_MS 1000 - -static int busbusy = false; //Set whenever an operation starts; reset by finishbus interrupt; -static Timer busbusytimer; - -static Timeout startbuslow; -static Timeout startbusfree; -static Timeout startbushigh; -static Timeout startbusread; -static Timeout startbusidle; -static void buslow (void) { pin.output(); pin = 0; } -static void busfree(void) { pin.input (); } -static void bushigh(void) { pin.output(); pin = 1; } -static void busread(void) { busvalue = pin; } -static void busidle(void) { pin.input (); busbusy = false; } +#define BUS_TIMEOUT_MS 5000 -static void reset() -{ - busbusy = true; - int start = INITIAL_US - ATTACH_US; startbuslow .attach_us(&buslow, start); - start += RESET_BUS_LOW_US - ATTACH_US; startbusfree.attach_us(&busfree, start); - start += READ_PRESENCE_US - ATTACH_US; startbusread.attach_us(&busread, start); - start += RESET_RELEASE_US - ATTACH_US; startbusidle.attach_us(&busidle, start); -} -static void writebit(int bit, int msToPullUp) -{ - busbusy = true; - int start = INITIAL_US - ATTACH_US; - startbuslow.attach_us(&buslow, start); - start += bit ? WRITE_1_BUS_LOW_US : WRITE_0_BUS_LOW_US; - start -= ATTACH_US; - if (msToPullUp) - { - startbushigh.attach_us(&bushigh, start); - start += msToPullUp * 1000 - ATTACH_US; - } - else - { - startbusfree.attach_us(&busfree, start); - start += bit ? WRITE_1_RELEASE_US : WRITE_0_RELEASE_US; - start -= ATTACH_US; - } - startbusidle.attach_us(&busidle, start); -} -static void initiatebitread() -{ - busbusy = true; - int start = INITIAL_US - ATTACH_US; startbuslow .attach_us(&buslow, start); - start += READ_BIT_BUS_LOW_US - ATTACH_US; startbusfree.attach_us(&busfree, start); - start += READ_BIT_US - ATTACH_US; startbusread.attach_us(&busread, start); - start += READ_BIT_RELEASE_US - ATTACH_US; startbusidle.attach_us(&busidle, start); -} +static void buslow (void) { pin.output(); pin = 0; } +static void busfree(void) { pin.input (); } +static void bushigh(void) { pin.output(); pin = 1; } +static void busread(void) { busvalue = pin; } //Exchange zone //============= -#define XCHG_IDLE 0 -#define XCHG_RESET 1 -#define XCHG_WRITE 2 -#define XCHG_READ 3 -#define XCHG_PULLUP 4 -static int xchgstate = XCHG_IDLE; +#define STATE_IDLE 0 +#define RESET_LOW 1 +#define RESET_RELEASE 2 +#define XCHG_WRITE 3 +#define PULL_UP 4 +#define XCHG_READ 5 +#define SEARCH_WRITE 6 +#define SEARCH_BIT 7 +#define SEARCH_READ_BIT_TRUE 8 +#define SEARCH_READ_BIT_COMP 9 +#define SEARCH_WRITE_BIT 10 +static int state = STATE_IDLE; + +#define JOB_NONE 0 +#define JOB_XCHG 1 +#define JOB_SEARCH 2 +static int job = JOB_NONE; static int lensend = 0; static int lenrecv = 0; @@ -90,6 +58,52 @@ static char* precv = NULL; static int pullupms = 0; +static void initiateResetLow(int jobtype) +{ + buslow(); + timer.stop(); + timer.reset(); + timer.start(); + state = RESET_LOW; + job = jobtype; +} +static void readPresenceAndAwaitResetRelease() +{ + busfree(); + wait_us(READ_PRESENCE_US); + busread(); + timer.stop(); + timer.reset(); + timer.start(); + state = RESET_RELEASE; +} +static void writeBit(int bit) +{ + buslow(); + wait_us(bit ? WRITE_1_BUS_LOW_US : WRITE_0_BUS_LOW_US); + busfree(); + wait_us(bit ? WRITE_1_RELEASE_US : WRITE_0_RELEASE_US); +} +static void writeBitWithPullUp(int bit) +{ + buslow(); + wait_us(bit ? WRITE_1_BUS_LOW_US : WRITE_0_BUS_LOW_US); + bushigh(); + timer.stop(); + timer.reset(); + timer.start(); + state = PULL_UP; +} +static void readBit() +{ + buslow(); + wait_us(READ_BIT_BUS_LOW_US); + busfree(); + wait_us(READ_BIT_US); + busread(); + wait_us(READ_BIT_RELEASE_US); +} + static char crc; static void resetCrc() { @@ -97,14 +111,9 @@ } static void addBitToCrc(int bit) { - //Logical Exclusive Or of the 9th output of the shift register with the input - int feedback = !(crc & 0x80) != !bit; - - //Move the shift register one place to the left leaving a zero in the lsb - crc <<= 1; - - //Exclusive Or the shift register with polynomial X5 + X4 + 1 - if (feedback) crc ^= 0x31; + int feedback = !(crc & 0x80) != !bit; //Logical Exclusive Or of the msb of the shift register with the input + crc <<= 1; //Move the shift register one place to the left leaving a zero in the lsb and losing the msb + if (feedback) crc ^= 0x31; //Exclusive Or the shift register with polynomial X5 + X4 + 1 } static void resetBitPosition(int* pByteIndex, char* pBitMask) @@ -128,7 +137,8 @@ } void setBitAtPosition(int byteIndex, char bitMask, int bit) { - if (bit) precv[byteIndex] |= bitMask; + if ( bit) precv[byteIndex] |= bitMask; + else precv[byteIndex] &= ~bitMask; } int moreBitsToRead(int byteIndex) { @@ -138,22 +148,24 @@ { return byteIndex < lensend; } + +int result = ONE_WIRE_RESULT_OK; +int OneWireResult() +{ + return result; +} int OneWireInit() { - startbuslow.detach(); - startbushigh.detach(); - startbusfree.detach(); - startbusread.detach(); - startbusidle.detach(); - busidle(); - xchgstate = XCHG_IDLE; - busbusytimer.stop(); - busbusytimer.reset(); + busfree(); + busytimer.stop(); + busytimer.reset(); + state = STATE_IDLE; + job = JOB_NONE; return 0; } int OneWireBusy() { - return xchgstate; + return state; } void OneWireExchange(int lenBytesToSend, int lenBytesToRecv, char *pBytesToSend, char *pBytesToRecv, int msToPullUp) { @@ -162,8 +174,66 @@ psend = pBytesToSend; precv = pBytesToRecv; pullupms = msToPullUp; - xchgstate = XCHG_RESET; - reset(); + initiateResetLow(JOB_XCHG); +} +static int* pallfound; +static char* prom; +static void setRomBit(int position, int bit) +{ + int bitindex = position & 0x07; + int byteindex = position >> 3; + int bitmask = 1 << bitindex; + if (bit) *(prom + byteindex) |= bitmask; + else *(prom + byteindex) &= ~bitmask; +} +static int getRomBit(int position) +{ + int bitindex = position & 0x07; + int byteindex = position >> 3; + int bitmask = 1 << bitindex; + return *(prom + byteindex) & bitmask; +} +static int thisFurthestForkLeftPosn; +static int lastFurthestForkLeftPosn; +static char searchCommand; +static int searchBitPosn; +static int searchBitTrue; +static int searchBitComp; +static int chooseDirectionToTake() +{ + if ( searchBitTrue && searchBitComp) return -1; //No devices are participating in the search + if ( searchBitTrue && !searchBitComp) return 1; //Only devices with a one at this point are participating + if (!searchBitTrue && searchBitComp) return 0; //Only devices with a zero at this point are participating + //Both bits are zero so devices with both 0s and 1s at this point are still participating + + //If we have not yet reached the furthest away point we forked left (0) last time then just do whatever we did last time + if (searchBitPosn < lastFurthestForkLeftPosn) return getRomBit(searchBitPosn); + + //If we are at the furthest away point that we forked left (0) last time then this time fork right (1) + if (searchBitPosn == lastFurthestForkLeftPosn) return 1; + + //We are at a new fork point further than we have been before so fork left (0) and record that we did so. + thisFurthestForkLeftPosn = searchBitPosn; + return 0; +} +void OneWireSearch(char command, char* pDeviceRom, int* pAllDevicesFound) //Specify the buffer to receive the rom for the first search and NULL thereafter. +{ + if (pDeviceRom) + { + pallfound = pAllDevicesFound; + *pallfound = false; + lastFurthestForkLeftPosn = -1; + prom = pDeviceRom; + for (int i = 0; i < 8; i++) *(prom + i) = 0; + } + thisFurthestForkLeftPosn = -1; + lensend = 1; + lenrecv = 0; + searchCommand = command; + psend = &searchCommand; + precv = NULL; + pullupms = 0; + initiateResetLow(JOB_SEARCH); } char OneWireCrc() { @@ -174,45 +244,64 @@ static int byteindex; static char bitmask; - if (busbusy) + if (state) { - busbusytimer.start(); - if (busbusytimer.read_ms() > BUS_TIMEOUT_MS) + busytimer.start(); + if (busytimer.read_ms() > BUS_TIMEOUT_MS) { LogCrLf("1-wire bus timed out so protocol has been reset to idle."); OneWireInit(); + result = ONE_WIRE_RESULT_TIMED_OUT; + return 0; } - return 0; } else { - busbusytimer.stop(); - busbusytimer.reset(); + busytimer.stop(); + busytimer.reset(); } - switch(xchgstate) + switch(state) { - case XCHG_IDLE: + case STATE_IDLE: break; - case XCHG_RESET: - if (busvalue) + case RESET_LOW: + if (timer.read_us() > RESET_BUS_LOW_US) readPresenceAndAwaitResetRelease(); + break; + case RESET_RELEASE: + if (timer.read_us() > RESET_RELEASE_US) { - LogCrLf("No 1-wire device presence detected on the bus"); - xchgstate = XCHG_IDLE; - } - else - { - resetBitPosition(&byteindex, &bitmask); - xchgstate = XCHG_WRITE; + busfree(); + timer.stop(); + timer.reset(); + if (busvalue) + { + LogCrLf("No 1-wire device presence detected on the bus"); + result = ONE_WIRE_RESULT_NO_DEVICE_PRESENT; + state = STATE_IDLE; + } + else + { + resetBitPosition(&byteindex, &bitmask); + switch (job) + { + case JOB_XCHG: state = XCHG_WRITE; break; + case JOB_SEARCH: state = SEARCH_WRITE; break; + default: + LogF("Unknown job in RESET_RELEASE %d\r\n", job); + return -1; + } + } } break; + case XCHG_WRITE: if (moreBitsToWrite(byteindex)) { int bit = getBitAtPosition(byteindex, bitmask); incrementBitPosition(&byteindex, &bitmask); - if (moreBitsToWrite(byteindex)) writebit(bit, 0); - else writebit(bit, pullupms); + if (moreBitsToWrite(byteindex)) writeBit(bit); + else writeBitWithPullUp(bit); } else { @@ -220,31 +309,102 @@ if (moreBitsToRead(byteindex)) { resetCrc(); - initiatebitread(); - xchgstate = XCHG_READ; + readBit(); + state = XCHG_READ; } else { - xchgstate = XCHG_IDLE; + result = ONE_WIRE_RESULT_OK; + state = STATE_IDLE; } } break; + case PULL_UP: + if (timer.read_ms() > pullupms) + { + busfree(); + switch (job) + { + case JOB_XCHG: state = XCHG_WRITE; break; + default: + LogF("Unknown job in PULL_UP %d\r\n", job); + return -1; + } + } + break; case XCHG_READ: addBitToCrc(busvalue); setBitAtPosition(byteindex, bitmask, busvalue); incrementBitPosition(&byteindex, &bitmask); if (moreBitsToRead(byteindex)) { - initiatebitread(); + readBit(); + } + else + { + state = STATE_IDLE; + result = crc ? ONE_WIRE_RESULT_CRC_ERROR : ONE_WIRE_RESULT_OK; + } + break; + + case SEARCH_WRITE: + if (moreBitsToWrite(byteindex)) + { + int bit = getBitAtPosition(byteindex, bitmask); + incrementBitPosition(&byteindex, &bitmask); + writeBit(bit); } else { - xchgstate = XCHG_IDLE; + searchBitPosn = 0; + state = SEARCH_BIT; + } + break; + case SEARCH_BIT: + readBit(); + state = SEARCH_READ_BIT_TRUE; + break; + case SEARCH_READ_BIT_TRUE: + searchBitTrue = busvalue; + readBit(); + state = SEARCH_READ_BIT_COMP; + break; + case SEARCH_READ_BIT_COMP: + searchBitComp = busvalue; + state = SEARCH_WRITE_BIT; + break; + case SEARCH_WRITE_BIT: + LogF("%d%d - ", searchBitTrue, searchBitComp); + int direction; + direction = chooseDirectionToTake(); + if (direction == -1) + { + LogCrLf("No devices have responded"); + result = ONE_WIRE_RESULT_NO_DEVICE_PARTICIPATING; + state = STATE_IDLE; + } + else + { + LogF(" %d -> %d\r\n", direction, searchBitPosn); + setRomBit(searchBitPosn, direction); + writeBit(direction); + searchBitPosn++; + if (searchBitPosn < 64) + { + state = SEARCH_BIT; + } + else + { + if (thisFurthestForkLeftPosn == -1) *pallfound = true; + lastFurthestForkLeftPosn = thisFurthestForkLeftPosn; + result = ONE_WIRE_RESULT_OK; + state = STATE_IDLE; + } } break; default: - LogF("Unknown xchgstate %d\r\n", xchgstate); + LogF("Unknown state %d\r\n", state); return -1; } return 0;