Backing up an unused program in case of future need

Dependencies:   mbed

1-wire.cpp

Committer:
andrewboyson
Date:
2018-12-06
Revision:
8:45a0205a298f
Parent:
7:024ace6d943c

File content as of revision 8:45a0205a298f:

#include   "mbed.h"
#include    "log.h"
#include     "io.h"
#include "1-wire.h"

#define DEBUG false //Set to true to add debug messages to the log

//Bus zone
//========
static DigitalInOut pin(p25, PIN_INPUT, PullUp, 0);

static volatile int busvalue;

static Timer timer;
static Timer busytimer;

//Delays
#define           ATTACH_US    7
#define          INITIAL_US  100
#define    RESET_BUS_LOW_US  480
#define    READ_PRESENCE_US   70
#define    RESET_RELEASE_US  410
#define  WRITE_0_BUS_LOW_US   60
#define  WRITE_0_RELEASE_US   10
#define  WRITE_1_BUS_LOW_US    6
#define  WRITE_1_RELEASE_US   64
#define READ_BIT_BUS_LOW_US    6
#define         READ_BIT_US    9
#define READ_BIT_RELEASE_US   55
#define      BUS_TIMEOUT_MS 5000

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 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;
static char*  psend = NULL;
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()
{
    crc = 0;
}
static void addBitToCrc(int bit)
{
    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)
{
    *pBitMask = 1;
    *pByteIndex = 0;
}
static void incrementBitPosition(int* pByteIndex, char* pBitMask)
{
    *pBitMask <<= 1;
    if (!*pBitMask)
    {
        *pBitMask = 1;
        *pByteIndex += 1;
    }
}

int getBitAtPosition(int byteIndex, char bitMask)
{
    return psend[byteIndex] & bitMask;
}
void setBitAtPosition(int byteIndex, char bitMask, int bit)
{
    if ( bit) precv[byteIndex] |=  bitMask;
    else      precv[byteIndex] &= ~bitMask;
}
int moreBitsToRead(int byteIndex)
{
    return byteIndex < lenrecv;
}
int moreBitsToWrite(int byteIndex)
{
    return byteIndex < lensend;
}

int result = ONE_WIRE_RESULT_OK;
int OneWireResult()
{
    return result;
}
int OneWireInit()
{
    busfree();
    busytimer.stop();
    busytimer.reset();
    state = STATE_IDLE;
    job   =  JOB_NONE;
    return 0;
}
int OneWireBusy()
{
    return state;
}
void OneWireExchange(int lenBytesToSend, int lenBytesToRecv, char *pBytesToSend, char *pBytesToRecv, int msToPullUp)
{
    lensend = lenBytesToSend;
    lenrecv = lenBytesToRecv;
    psend = pBytesToSend;
    precv = pBytesToRecv;
    pullupms = msToPullUp;
    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()
{
    return crc;
}
int OneWireMain()
{
    static int byteindex;
    static char bitmask;
    
    if (state)
    {
        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;
        }
    }
    else
    {
        busytimer.stop();
        busytimer.reset();
    }
    
    switch(state)
    {
        case STATE_IDLE:
            break;
        case RESET_LOW:
            if (timer.read_us() > RESET_BUS_LOW_US) readPresenceAndAwaitResetRelease();
            break;
        case RESET_RELEASE:
            if (timer.read_us() > RESET_RELEASE_US)
            {
                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);
                else                            writeBitWithPullUp(bit);
            }
            else
            {
                resetBitPosition(&byteindex, &bitmask);
                if (moreBitsToRead(byteindex))
                {
                    resetCrc();
                    readBit();
                    state = XCHG_READ;
                    
                }
                else
                {
                    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))
            {
                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
            {
                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:
            if (DEBUG) 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
            {
                if (DEBUG) 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 state %d\r\n", state);
            return -1;
    }
    return 0;
}