?lang_form? ?lang_select? ?lang_submit? ?lang_endform?
{HEADER END}
{FILE START}

library

?curdirlinks? - Rev 6

?prevdifflink? - Blame - ?getfile?

//*****************************************************************************
// File Name    : dallas.c
// Title                : Dallas 1-Wire Library
// Revision             : 6
// Notes                : 
// Target MCU   : Atmel AVR series
// Editor Tabs  : 4
// 
//*****************************************************************************
 
//----- Include Files ---------------------------------------------------------
#include <avr/io.h>                             // include I/O definitions (port names, pin names, etc)
#include <avr/interrupt.h>              // include interrupt support
#include <string.h>                             // include string support
#include "rprintf.h"                    // include rprintf function library
#include "timer128.h"                   // include timer function library
#include "dallas.h"                             // include dallas support

//----- Global Variables -------------------------------------------------------
static u08 last_discrep = 0;    // last discrepancy for FindDevices
static u08 done_flag = 0;               // done flag for FindDevices

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

//----- Functions --------------------------------------------------------------

/*--------------------------------------------------------------------------
 * dallasFindNextDevice: find the next device on the bus
 * input................ rom_id - pointer to store the rom id found
 * returns.............. true or false if a device was found
 *-------------------------------------------------------------------------*/
u08 dallasFindNextDevice(dallas_rom_id_T* rom_id);

void dallasDelayUs(u16 us)
{
        while(us--) // 6 cycles
        {
                asm volatile ("nop");
                asm volatile ("nop");
                asm volatile ("nop");
                asm volatile ("nop");
                asm volatile ("nop");
                asm volatile ("nop");
                asm volatile ("nop");
        } // loop jump 2 cycles
}

void dallasInit(void)
{
}

u08 dallasReset(void)
{
        u08 presence = DALLAS_PRESENCE;

        cli();
        
        // pull line low
        sbi(DALLAS_DDR, DALLAS_PIN);
        cbi(DALLAS_PORT, DALLAS_PIN);
        
        // wait for presence
        dallasDelayUs(480);
        
        // allow line to return high
        cbi(DALLAS_DDR, DALLAS_PIN);
        sbi(DALLAS_PORT, DALLAS_PIN);
        
        // wait for presence
        dallasDelayUs(70);

        // if device is not present, pin will be 1
        if (inb(DALLAS_PORTIN) & 0x01<<DALLAS_PIN)
                presence = DALLAS_NO_PRESENCE;

        // wait for end of timeslot
        dallasDelayUs(410);

        sei();

        // now that we have reset, let's check bus health
        // it should be noted that a delay may be needed here for devices that
        // send out an alarming presence pulse signal after a reset
        cbi(DALLAS_DDR, DALLAS_PIN);
        sbi(DALLAS_PORT, DALLAS_PIN);
        //dallasDelayUs(200);
        if (!(inb(DALLAS_PORTIN) & (0x01<<DALLAS_PIN))) // it should be pulled up to high
                return DALLAS_BUS_ERROR;

        return presence;
}

u08 dallasReadBit(void)
{
        u08 bit = 0;
        
        // pull line low to start timeslot
        sbi(DALLAS_DDR, DALLAS_PIN);
        cbi(DALLAS_PORT, DALLAS_PIN);
        
        // delay appropriate time
        dallasDelayUs(6);

        // release the bus
        cbi(DALLAS_DDR, DALLAS_PIN);
        sbi(DALLAS_PORT, DALLAS_PIN);
        
        // delay appropriate time       
        dallasDelayUs(9);

        // read the pin and set the variable to 1 if the pin is high
        if (inb(DALLAS_PORTIN) & 0x01<<DALLAS_PIN)
                bit = 1;
        
        // finish read timeslot
        dallasDelayUs(55);
        
        return bit;
}

void dallasWriteBit(u08 bit)
{
        // drive bus low
        sbi(DALLAS_DDR, DALLAS_PIN);
        cbi(DALLAS_PORT, DALLAS_PIN);
        
        // delay the proper time if we want to write a 0 or 1
        if (bit)
                dallasDelayUs(6);
        else
                dallasDelayUs(60);

        // release bus
        cbi(DALLAS_DDR, DALLAS_PIN);
        sbi(DALLAS_PORT, DALLAS_PIN);

        // delay the proper time if we want to write a 0 or 1
        if (bit)
                dallasDelayUs(64);
        else
                dallasDelayUs(10);
}

u08 dallasReadByte(void)
{
        u08 i;
        u08 byte = 0;

        cli();
        
        // read all 8 bits
        for(i=0;i<8;i++)
        {
                if (dallasReadBit())
                        byte |= 0x01<<i;

                // allow a us delay between each read
                dallasDelayUs(1);
        }

        sei();

        return byte;
}

void dallasWriteByte(u08 byte)
{
        u08 i;

        cli();

        // write all 8 bits
        for(i=0;i<8;i++)
        {
                dallasWriteBit((byte>>i) & 0x01);
                
                // allow a us delay between each write
                dallasDelayUs(1);
        }
        
        sei();
}

u08 dallasReadRAM(dallas_rom_id_T* rom_id, u16 addr, u08 len, u08 *data)
{
        u08 i;
        u08 error;

        union int16_var_U
        {
                u16 i16;
                u08 i08[2];
        } int16_var;

        // first make sure we actually have something to do
        if (data == NULL)
                return DALLAS_NULL_POINTER;
        if (len == 0)
                return DALLAS_ZERO_LEN;

        // reset the bus and request the device
        error = dallasMatchROM(rom_id);
        if (error != DALLAS_NO_ERROR)
                return error;
        
        // enter read mode
        dallasWriteByte(DALLAS_READ_MEMORY);
        
        // write address one byte at a time
        int16_var.i16 = addr;
        dallasWriteByte(int16_var.i08[0]);
        dallasWriteByte(int16_var.i08[1]);
        
        // read data from device 1 byte at a time
        for(i=0;i<len;i++)
                data[i] = dallasReadByte();

        return DALLAS_NO_ERROR;
}

u08 dallasWriteRAM(dallas_rom_id_T* rom_id, u16 addr, u08 len, u08* data)
{
        u08 i;
        u08 error;

        union int16_var_U
        {
                u16 i16;
                u08 i08[2];
        } int16_var;

        // first make sure we actually have something to do
        if (data == NULL)
                return DALLAS_NULL_POINTER;
        if (len == 0)
                return DALLAS_ZERO_LEN;

        // reset the bus and request the device
        error = dallasMatchROM(rom_id);
        if (error != DALLAS_NO_ERROR)
                return error;
        
        // enter write mode
        dallasWriteByte(DALLAS_WRITE_MEMORY);

        // write address one byte at a time
        int16_var.i16 = addr;
        dallasWriteByte(int16_var.i08[0]);
        dallasWriteByte(int16_var.i08[1]);
        
        // write data one byte at a time
        for(i=0;i<len;i++)
        {
                dallasWriteByte(data[i]);
                
                // future: Check CRC16, for now just read it so we can go on
                dallasReadByte();
                dallasReadByte();

                // verify the data
                if (dallasReadByte() != data[i])
                        return DALLAS_VERIFY_ERROR;
        }

        return DALLAS_NO_ERROR;
}

void dallasWaitUntilDone(void)
{
        //timerPause(6);
        
        // wait until we recieve a one
        cli();
        while(!dallasReadBit());
        sei();
}

u08 dallasReadROM(dallas_rom_id_T* rom_id)
{
        u08 i;

        // reset the 1-wire bus and look for presence
        i = dallasReset();
        if (i != DALLAS_PRESENCE)
                return i;
        
        // send READ ROM command
        dallasWriteByte(DALLAS_READ_ROM);

        // get the device's ID 1 byte at a time
        for(i=0;i<8;i++)
                rom_id->byte[i] = dallasReadByte();

        return DALLAS_NO_ERROR;
}

u08 dallasMatchROM(dallas_rom_id_T* rom_id)
{
        u08 i;

        // reset the 1-wire and look for presence
        i = dallasReset();
        if (i != DALLAS_PRESENCE)
                return i;

        // send MATCH ROM command
        dallasWriteByte(DALLAS_MATCH_ROM);

        // write id one byte at a time
        for(i=0;i<8;i++)
                dallasWriteByte(rom_id->byte[i]);

        return DALLAS_NO_ERROR;
}

void dallasPrintROM(dallas_rom_id_T* rom_id)
{
        s08 i;

        // print out the rom in the format: xx xx xx xx xx xx xx xx
        for(i=7;i>=0;i--)
        {
                rprintfu08(rom_id->byte[i]);
                rprintfChar(' ');
        }

        // print out the rom in the format: 0xXXXXXXXXXXXXXXXX
        rprintfProgStrM(" (0x");
        for(i=7;i>=0;i--)
        {
                rprintfu08(rom_id->byte[i]);
        }
        rprintfProgStrM("ULL)");

}

u08 dallasAddressCheck(dallas_rom_id_T* rom_id, u08 family)
{
//      u08 i;

//      dallas_crc = 0;
        
//      for(i=1;i<7;i++)
//      {
//              dallasCRC(rom_id->byte[i]);
//              rprintfu08(rom_id->byte[i]);
//              rprintfChar(' ');
//      }
//      rprintfCRLF();

//      rprintfu08(dallas_crc);
//      rprintfCRLF();
        
        //run CRC on address

        //make sure we have the correct family
        if (rom_id->byte[DALLAS_FAMILY_IDX] == family)
                return DALLAS_NO_ERROR;
        
        return DALLAS_ADDRESS_ERROR;
}

u08 dallasCRC(u08 i)
{
        // update the crc global variable and return it
        dallas_crc = dallas_crc_table[dallas_crc^i];
        return dallas_crc;
}

u08 dallasFindDevices(dallas_rom_id_T rom_id[])
{
        u08 num_found = 0;
        dallas_rom_id_T id;

        // reset the rom search last discrepancy global
        last_discrep = 0;
        done_flag = FALSE;

        // check to make sure presence is detected before we start
        if (dallasReset() == DALLAS_PRESENCE)
        {
                // --> stang
                //while (dallasFindNextDevice(&rom_id[num_found]) && (num_found<DALLAS_MAX_DEVICES))
                //      num_found++;
                
                // continues until no additional devices are found
                while (dallasFindNextDevice(&id) && (num_found<DALLAS_MAX_DEVICES))
                        memcpy(&rom_id[num_found++], &id, 8);
        }

        return num_found;
}

u08 dallasFindNextDevice(dallas_rom_id_T* rom_id)
{
        u08 bit;
        u08 i = 0;
        u08 bit_index = 1;
        u08 byte_index = 0;
        u08 bit_mask = 1;
        u08 discrep_marker = 0;
        
        // reset the CRC
        dallas_crc = 0;

        if (done_flag || dallasReset() != DALLAS_PRESENCE)
        {
                // no more devices parts detected
                return FALSE;
        }

        // send search ROM command
        dallasWriteByte(DALLAS_SEARCH_ROM);
        
        // loop until through all 8 ROM bytes
        while(byte_index<8)
        {
                // read line 2 times to determine status of devices
                //    00 - devices connected to bus with conflicting bits
                //    01 - all devices have a 0 in this position
                //    10 - all devices ahve a 1 in this position
                //    11 - there are no devices connected to bus
                i = 0;
                cli();
                if (dallasReadBit())
                        i = 2;                          // store the msb if 1
                dallasDelayUs(120);
                if (dallasReadBit())
                        i |= 1;                         // store the lsb if 1
                sei();
                
                if (i==3)
                {
                        // there are no devices on the 1-wire
                        break;
                }
                else
                {
                        if (i>0)
                        {
                                // all devices coupled have 0 or 1
                                // shift 1 to determine if the msb is 0 or 1
                                bit = i>>1;
                        }
                        else
                        {
                                // if this discrepancy is before the last discrepancy on a
                                // previous FindNextDevice then pick the same as last time
                                if (bit_index<last_discrep)
                                        bit = ((rom_id->byte[byte_index] & bit_mask) > 0);
                                else
                                        bit = (bit_index==last_discrep);
                                
                                // if 0 was picked then record position with bit mask
                                if (!bit)
                                        discrep_marker = bit_index;
                        }

                        // isolate bit in rom_id->byte[byte_index] with bit mask
                        if (bit)
                                rom_id->byte[byte_index] |= bit_mask;
                        else
                                rom_id->byte[byte_index] &= ~bit_mask;

                        // ROM search write
                        cli();
                        dallasWriteBit(bit);
                        sei();

                        // ncrement bit index counter and shift the bit mask
                        bit_index++; 
                        bit_mask <<= 1;
                        
                        if (!bit_mask)
                        {
                                // if the mask is 0 then go to new ROM
                                // accumulate the CRC and incriment the byte index and bit mask
                                dallasCRC(rom_id->byte[byte_index]);
                                byte_index++;
                                bit_mask++;
                        }
                }
        }

        if ((bit_index < 65) || dallas_crc)
        {
                // search was unsuccessful - reset the last discrepancy to 0 and return false
                last_discrep = 0;
                return FALSE;
        }

        // search was successful, so set last_discrep and done_flag
        last_discrep = discrep_marker;
        done_flag = (last_discrep==0);

        return TRUE;
}

void dallasPrintError(u08 error)
{
        // if there was not an error, return
        if (error == DALLAS_NO_ERROR)
                return;
        
        // print header message
        rprintfProgStrM("ERROR ");
        rprintfChar(error);
        rprintfProgStrM(": ");

        // print custom error message
        switch (error)
        {
                case DALLAS_NO_PRESENCE:
                        rprintfProgStrM("no presence detected");
                        break;
                case DALLAS_INVALID_CHANNEL:
                        rprintfProgStrM("Invalid Chan");
                        break;
                case DALLAS_VERIFY_ERROR:
                        rprintfProgStrM("Verify");
                        break;
                case DALLAS_ADDRESS_ERROR:
                        rprintfProgStrM("Bad Addr");
                        break;
                case DALLAS_CRC_ERROR:
                        rprintfProgStrM("Data CRC");    
                        break;
                case DALLAS_DEVICE_ERROR:
                        rprintfProgStrM("No response");
                        break;
                case DALLAS_FORMAT_ERROR:
                        rprintfProgStrM("Bad return format");
                        break;
                case DALLAS_NULL_POINTER:
                        rprintfProgStrM("Null Pointer");
                        break;
                case DALLAS_ZERO_LEN:
                        rprintfProgStrM("RAM rd/wr 0 bytes");
                        break;
                case DALLAS_BUS_ERROR:
                        rprintfProgStrM("Bus error, check pullup");
                        break;
                case DALLAS_RESOLUTION_ERROR:
                        rprintfProgStrM("resolution out of range");
                        break;
                default:
                        rprintfProgStrM("Unknown");
        }
        rprintfCRLF();
}
{FILE END}
{FOOTER START}

Powered by WebSVN v2.8.3