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

library

?curdirlinks? - Rev 6

?prevdifflink? - Blame - ?getfile?

//*****************************************************************************
// File Name    : ds2450.c
// Title                : Dallas 1-Wire DS2450 A2D Sensor Library
// Revision             : 5
// Notes                : 
// Target MCU   : Atmel AVR series
// Editor Tabs  : 4
// 
//*****************************************************************************

//----- Include Files ---------------------------------------------------------
#include <string.h>                     // include string support
#include <ctype.h>
#include "timer128.h"
#include "dallas.h"                     // include dallas support
#include "ds2450.h"                     // include ds2450 support
#include "rprintf.h"

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

/*--------------------------------------------------------------------------
 * ds2450Chan2Addr: converts the channel to the address in RAM
 * input........... channel - the channel to get the address for [A-D]
 *                  page - the page in RAM that we are dealing with
 *                  address - where the address is stored
 * returns......... the corresponding error or DALLAS_NO_ERROR
 *-------------------------------------------------------------------------*/
static u08 ds2450Chan2Addr(u08 channel, u08 page, u16 *address);

void ds2450Init(void)
{
        // initialize the dallas 1-wire
        dallasInit();
}

u08 *capitalize (u08 *input)
{
        if(islower(*input))
                *input = toupper(*input);
        return input;
}

u08 ds2450Setup(dallas_rom_id_T* rom_id, u08 channel, u08 resolution, u08 range)
{
        u08 error;
        u08 data[2];
        u16 address;

        // check resolution
        if (resolution > DS2450_RES_MAX)
                return DALLAS_RESOLUTION_ERROR;

        // check address
        error = dallasAddressCheck(rom_id, DS2450_FAMILY);
        if (error != DALLAS_NO_ERROR)
                return error;

        // get address
        capitalize(&channel);
        error = ds2450Chan2Addr(channel, DS2450_SETUP_PAGE, &address);  //find starting address
        if (error != DALLAS_NO_ERROR)
                return error;

        // convert to valid resolution - 16 bits = 0x00
        if (resolution == 16)
                resolution = 0x00;

        // read in current digital output settings
        error = dallasReadRAM(rom_id, address, 1, data);
        if (error != DALLAS_NO_ERROR)
                return error;

        // maintain digital output portion and add new resolution
        data[0] = (data[0] & 0xF0) | resolution;
        
        // maintain alarm states and add new range
        data[1] = (data[1] & 0xFE) | range;

        // actually write config, handles CRC too
        error = dallasWriteRAM(rom_id, address, 2, data);
        if (error != DALLAS_NO_ERROR)
                return error;

        // Normally, the DS2450 is designed to run off of parasite power from the data line
        // Typically the master (us) strongly pulls high long enough to power the conversion, so
        // there is inherintly a long () delay introduced. Since the A2D code is designed to
        // work for devices that use external power, we can elliminate this delay by writting
        // the following byte per the DS2450 datasheet.
        data[0] = DS2450_VCC_FLAG;
        error = dallasWriteRAM(rom_id, DS2450_VCC_ADDR, 1, &data[0]);
        if (error != DALLAS_NO_ERROR)
                return error;

        // verify the data
        error = dallasReadRAM(rom_id, address, 2, data);
        if (error != DALLAS_NO_ERROR)
                return error;

        if ((data[0] & 0x0F) != resolution)
                return DALLAS_VERIFY_ERROR;
        if ((data[1] & 0x01) != range)
                return DALLAS_VERIFY_ERROR;

        return DALLAS_NO_ERROR;
}

u08 ds2450Start(dallas_rom_id_T* rom_id, u08 channel)
{
        u08 mask;
        u08 error;
        u08 crc[2];

        // check address
        error = dallasAddressCheck(rom_id, DS2450_FAMILY);
        if (error != DALLAS_NO_ERROR)
                return error;

        // make sure the channel is a capital letter
        capitalize(&channel);
        // convert to integer 0 to 3
        channel -= 'A';

        // make sure channel is a valid value
        if (channel > 3)
                return DALLAS_INVALID_CHANNEL;

        // shift over to construct input select mask
        mask = 0x01 << channel;

        // reset and select node
        error = dallasMatchROM(rom_id);
        if (error != DALLAS_NO_ERROR)
                return error;

        // send convert command
        dallasWriteByte(DS2450_CONVERT);
        // input select mask
        dallasWriteByte(mask);
        // shift over some more for "read-out" control
        mask = mask << channel;
        
        // set coresponding output buffer to zero       
        dallasWriteByte(mask);

        // we must read 2byte CRC16 to start the conversion:
        crc[0] = dallasReadByte();
        crc[1] = dallasReadByte();

        //replace with explicit CRC posibilities lookup table
//      if (crc[0] == 0xFF && crc[1] == 0xFF)
//              return DALLAS_DEVICE_ERROR;        //if CRC = all one's, no one is paying attention

        return DALLAS_NO_ERROR;
}

u08 ds2450Result(dallas_rom_id_T* rom_id, u08 channel, u16* result)
{
        u08 data[2];
        u08 error;
        u16 address;
        //u08 resolution;

        // check address
        error = dallasAddressCheck(rom_id, DS2450_FAMILY);
        if( error != DALLAS_NO_ERROR)
                return error;

        // get the RAM address for the data for the channel
        capitalize(&channel);
        error = ds2450Chan2Addr(channel, DS2450_DATA_PAGE, &address);
        if (error != DALLAS_NO_ERROR)
                return error;

        // read the RAM from the device to get the data
        error = dallasReadRAM(rom_id, address, 2, data);
        /*
        // get the address for the setup for the channel
        error = ds2450Chan2Addr(channel, DS2450_SETUP_PAGE, &address);  //find starting address
        if (error != DALLAS_NO_ERROR)
                return error;
        
        // read the RAM from the device to get the resolution
        error = dallasReadRAM(rom_id, address, 1, &resolution);
        if (error != DALLAS_NO_ERROR)
                return error;

        // get the resultion part of the data
        resolution &=0x0F;
        */
        // store the result by combining the 2 bytes
        // the result's MSB is always the same, so we may need to
        // shift the data over so that the LSB is at the first bit
        *result = 0;
        //*result = (((u16)data[1] << 8) | data[0]) >> (16 - resolution);
        *result = (((u16)data[1] << 8) | data[0]);

        return DALLAS_NO_ERROR;
}

u08 ds2450StartAndResult(dallas_rom_id_T* rom_id, u08 channel, u16 *result)
{
        u08 error;

        // start conversion
        error = ds2450Start(rom_id, channel);
        if (error != DALLAS_NO_ERROR)
                return error;
        
        // wait till conversion done
        dallasWaitUntilDone();
        
        // return results
        return ds2450Result(rom_id, channel, result);
}

u08 ds2450SetupAll(dallas_rom_id_T* rom_id, u08 resolution, u08 range)
{
        u08 i;
        u08 error;
        u08 data[8];
        u16 address;

        // check address
        error = dallasAddressCheck(rom_id, DS2450_FAMILY);
        if (error != DALLAS_NO_ERROR)
                return error;

        // check resolution
        if (resolution > DS2450_RES_MAX)
                return DALLAS_RESOLUTION_ERROR;

        // convert to valid resolution - 16 bits = 0x00
        if (resolution == 16)
                resolution = 0;

        // get address - start with channel A
        error = ds2450Chan2Addr('A', DS2450_SETUP_PAGE, &address);
        if (error != DALLAS_NO_ERROR)
                return error;

        // read in current settings so we can extract digital part
        error = dallasReadRAM(rom_id, address, 8, data);
        if (error != DALLAS_NO_ERROR)
                return error;

        // build up config data to write - increment by 2 b/c two bytes per channel
        for(i=0;i<8;i+= 2)
        { 
                // maintain digital output settings
                data[i] &= 0xF0;        // extract digital output portion
                data[i+1] &= 0xFE;

                // write resolution byte and range
                data[i] |= resolution;
                data[i+1] |= range;
        }

        // actually write config - handles CRC too
        error = dallasWriteRAM(rom_id, address, 8, data);
        if (error != DALLAS_NO_ERROR)
                return error;

        // Normally, the DS2450 is designed to run off of parasite power from the data line
        // Typically the master (us) strongly pulls high long enough to power the conversion, so
        // there is inherintly a long () delay introduced. Since the A2D code is designed to
        // work for devices that use external power, we can elliminate this delay by writting
        // the following byte per the DS2450 datasheet.
        data[0] = DS2450_VCC_FLAG;
        error = dallasWriteRAM(rom_id, DS2450_VCC_ADDR, 1, &data[0]);
        if (error != DALLAS_NO_ERROR)
                return error;

        error = dallasReadRAM(rom_id,address,8,data);
        if (error != DALLAS_NO_ERROR)
                return error;

        for(i=0;i<8;i+=2)
        {
                if ((data[i] & 0x0F) != resolution)
                        return DALLAS_VERIFY_ERROR;
                if ((data[i+1] & 0x01) != range)
                        return DALLAS_VERIFY_ERROR;
        }

        return DALLAS_NO_ERROR;
}

u08 ds2450StartAll(dallas_rom_id_T* rom_id)
{
        u08 error;
        u16 crc;

        // check address
        error = dallasAddressCheck(rom_id, DS2450_FAMILY);
        if (error != DALLAS_NO_ERROR)
                return error;

        // reset and select node
        error = dallasMatchROM(rom_id);
        if (error != DALLAS_NO_ERROR)
                return error;

        dallasWriteByte(DS2450_CONVERT);                        // send convert command
        dallasWriteByte(DS2450_CONVERT_ALL4_MASK);      // select all 4 inputs
        dallasWriteByte(DS2450_CLEAR_ALL4_MASK);                // set all output buffers to zero

        // we must read 2byte CRC16 to start the conversion:
        crc = dallasReadByte() | ((u16)dallasReadByte() << 8);

        // replace with explicit CRC posibilities lookup table
//      if (crc == 0xFFFF)
//              return DALLAS_DEVICE_ERROR;        // if CRC = all one's, no one is paying attention
        
        return DALLAS_NO_ERROR;
}

u08 ds2450ResultAll(dallas_rom_id_T* rom_id, u16 result[4])
{
        //const u08 bytes_to_read = 10;         // read 10bytes = 2/ch*4ch + CRC
        u08 bytes_to_read = 10;
        u08 i;
        u08 error;
        u08 data[10];
        u08 resolution[10];
        u16 address;

        // check address
        
        error = dallasAddressCheck(rom_id, DS2450_FAMILY);
        if (error != DALLAS_NO_ERROR)
                return error;

        // start address with channel A
        error = ds2450Chan2Addr('A', DS2450_DATA_PAGE, &address);
        if (error != DALLAS_NO_ERROR)
                return error;

        // read the conversion data
        error = dallasReadRAM(rom_id, address, bytes_to_read, data);
        if (error != DALLAS_NO_ERROR)
                return error;

        //FUTURE: do a real CRC16 check

        // start address with channel A
        error = ds2450Chan2Addr('A', DS2450_SETUP_PAGE, &address);
        if (error != DALLAS_NO_ERROR)
                return error;

        // read the resolution data
        error = dallasReadRAM(rom_id, address, bytes_to_read, resolution);
        if (error != DALLAS_NO_ERROR)
                return error;

        // check crc?

        // store the result by combining the 2 bytes
        // the result's MSB is always the same, so we may need to
        // shift the data over so that the LSB is at the first bit
        error=0;
        for(i=0;i<8;i+=2)
        {
                resolution[i] &= 0x0F;
                if (!resolution[i])
                        resolution[i] = 16;

                result[error] = 0;
                //result[error] = (((u16)data[i+1] << 8) | data[i]) >> (16 - resolution[i]);
                result[error] = (((u16)data[i+1] << 8) | data[i]);
                error++;
        }

        return DALLAS_NO_ERROR;
}

u08 ds2450StartAndResultAll(dallas_rom_id_T* rom_id, u16 result[4])
{
        u08 error;

        // start Conversion
        error = ds2450StartAll(rom_id);
        if (error != DALLAS_NO_ERROR)
                return error;
        
        // wait until conversion done
        dallasWaitUntilDone();
        
        // return any error - results passed by reference
        return ds2450ResultAll(rom_id, result);
}

void ds2450Print(u16 result, u08 range)
{
        u16 vscale;

        rprintfProgStrM(" 0x");
        rprintfu16(result);
        rprintf("  ");
        if(range)
                vscale = 12800;
        else
                vscale = 25600;

        rprintfNum(10, 4, TRUE , ' ', result/vscale);
        rprintf(".");
        rprintfNum(10, 4, FALSE, '0', (((u32)(result%vscale))*10000)/vscale );
        rprintfProgStrM(" Volts");
}

u08 ds2450DigitalOut(dallas_rom_id_T* rom_id, u08 channel, dallas_a2d_out_T state)
{
        u08 error;
        u08 old_resolution;
        u16 address;

        // check address
        error = dallasAddressCheck(rom_id, DS2450_FAMILY);
        if (error != DALLAS_NO_ERROR)
                return error;

        // get the address for the channel in the setup page
        error = ds2450Chan2Addr(channel, DS2450_SETUP_PAGE, &address);
        if (error != DALLAS_NO_ERROR)
                return error;

        // read in current resolution
        error = dallasReadRAM(rom_id, address, 1, &old_resolution);
        if (error != DALLAS_NO_ERROR)
                return error;
        
        // extract resolution portion
        old_resolution &= 0x0F;

        // write new setup byte
        state |= old_resolution;
        error = dallasWriteRAM(rom_id, address, 1, ((u08*)&state));
        if (error != DALLAS_NO_ERROR)
                return error;

        return DALLAS_NO_ERROR;
}

static u08 ds2450Chan2Addr(u08 channel, u08 page, u16 *address)
{
        // make sure the channel is a capital letter
        capitalize(&channel);

        //convert to integer 0 to 3 and check to see if it is valid
        channel -= 'A';
        if (channel > 3)
                return DALLAS_INVALID_CHANNEL;

        // use corresponding memory address
        *address = (channel<<1) + page;                 // channel<<1 == channel*2, but faster

        return DALLAS_NO_ERROR;
}
{FILE END}
{FOOTER START}

Powered by WebSVN v2.8.3