Go Down

Topic: AD8555 library testing (Read 1 time) previous topic - next topic

Nov 07, 2013, 08:13 am Last Edit: Nov 08, 2013, 07:32 am by Ilya Volkov Reason: 1
Hi, All.

I wrote a library for programming AD8555/8556 op-amps from Analog Devices. It works fine with AD8556, but I don't have a AD8555 chip around.
Could someone test it with AD8555 at least in simulation mode?

link to github: https://github.com/ivolkov/AD8555

robtillaart

#1
Nov 07, 2013, 05:48 pm Last Edit: Nov 07, 2013, 06:13 pm by robtillaart Reason: 1
Hi, thanks for sharing,

I see a number of improvements in the lib, I will patch and post asap. Don't have a chip to test BTW.

I'll be back ;)

+ changed datatype to uint8_t where possible -> simplified the code in several places
+ added some loops to minimize footprint
+ added a function to replace repeating code
+ added header with version info ++
- TODO replace some magic numbers (0b00 etc) with #defines
- TODO look at the function names if they can be more descriptive SendField0  --> senStartBits()
Code: [Select]

//
//    FILE: AD8555.cpp
//  AUTHOR:
// VERSION: 0.1.01
//    DATE: 2013-11-07
// PURPOSE:
//
// HISTORY:
// 0.1.00 - 2011-11-07 initial version
// 0.1.01 - 2013-11-07 refactored
//
// Released to the public domain
//

#include "AD8555.h"

AD8555::AD8555(uint8_t outputPin)
{
    outPin = outputPin;
    digitalWrite(outPin, LOW); // first low then outputmode prevents a possible small HIGH spike.
    pinMode(outPin, OUTPUT);
}

bool AD8555::setSecondStageGain(uint8_t value)
{
    if (value > 7) return false;
    SSG = value;
    return true;
}

bool AD8555::setFirstStageGain(uint8_t value)
{
    if (value > 127) return false;
    FSG = value;
    return true;
}

bool AD8555::setOffset(uint8_t value)
{
    OFS = value;
    return true;
}

void AD8555::simulate()
{
    sendFields(0b01, 0b00, SSG);
    sendFields(0b01, 0b01, FSG);
    sendFields(0b01, 0b10, OFS);
}

//
// NEW FUNCTION
//
void AD8555::sendFields(uint8_t mode, uint8_t func, uint8_t value)
{
    sendField0();      // start packet
    sendField1(mode);
    sendField2(func);
    sendField3();
    sendField4(value);
    sendField5();      // stop packet
}


void AD8555::program()
{
    uint8_t par;

    for (uint8_t i = 0 ; i < 8 ; i++)
    {
        if (((SSG >> i) & 1) == 1)
        {
            par = (1 << i);
            blowSSGFuse(par);
        }
    }

    for (uint8_t i = 0 ; i < 8 ; i++)
    {
        if (((FSG >> i) & 1) == 1)
        {
            par = (1 << i);
            blowFSGFuse(par);
        }
    }

    for (uint8_t i = 0 ; i < 8 ; i++)
    {
        if (((OFS >> i) &1) == 1)
        {
            par = (1 << i);
            blowOFSFuse(par);
        }
    }

    blowMSF();
}

void AD8555::blowSSGFuse(unsigned char Value)
{
    sendFields(0b10, 0b00, Value);
    delay(1);
}

void AD8555::blowFSGFuse(unsigned char Value)
{
    sendFields(0b10, 0b01, Value);
    delay(1);
}

void AD8555::blowOFSFuse(unsigned char Value)
{
    sendFields(0b10, 0b10, Value);
    delay(1);
}

void AD8555::blowMSF()
{
    sendFields(0b10, 0b11, 0b00000001);
    delay(1);
}

void AD8555::sendField0()
{
    sendBit(1);
    for (uint8_t i=0; i<10; i++) sendBit(0);
    sendBit(1);
}

void AD8555::sendField1(uint8_t value)
{
    sendBit((value >> 1) & 1);
    sendBit(value & 1);
}

void AD8555::sendField2(uint8_t value)
{
    sendBit((value >> 1) & 1);
    sendBit(value & 1);
}

void AD8555::sendField3()
{
    sendBit(1);
    sendBit(0);
}

void AD8555::sendField4(uint8_t value)
{
    uint8_t i = 8;
    do
    {
        i--;
        sendBit((value >> i) & 1);
    }
    while(i > 0);
}

void AD8555::sendField5()
{
    sendBit(0);
    for (uint8_t i=0; i<10; i++) sendBit(1);
    sendBit(0);
}

void AD8555::sendBit(bool value)
{
    if (value) send1();
    else send0();
}

void AD8555::send0()
{
    digitalWrite(outPin, HIGH);
    digitalWrite(outPin, LOW);
    delayMicroseconds(500); // delay(0) is no delay...
}

void AD8555::send1()
{
    digitalWrite(outPin, HIGH);
    // why delay(0) that makes no sense ... use delayMicroseconds() to time very small units
    delayMicroseconds(500);
    digitalWrite(outPin, LOW);
    delayMicroseconds(500);
}


have a look
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Well that will be awesome. Opensource in action, whoohoo  :)

robtillaart

you need to adapt the .h file to get it to work of course
if there are questions just ask

(we will show the world that Russia and the Netherlands cooperate (more than 400yrs!) ;)

PS, you have to check the delay(0) remark in the code.
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Thanks! I've applied your suggestions to 'dev' branch. To be tested and merged to 'master' branch. It's always good to have someone to review your code.


PS, you have to check the delay(0) remark in the code.

Yeah... AD8555 may be nasty when it's come to timings. +/- 10 us may actually brick this device in some cases and I wasn't aware that Arduino has delayMicroseconds function (silly me) so I use this stupid delay(0) code. Thanks for pointing out that moment.

robtillaart

small issue
if (((SSG >> i) & 1) == 1)
can be written as
if ( (SSG >> i) & 1)
as every value not 0 is considered true. It is a well known practice in C.

With respect to delay(1), you should note that delayMIcros(1000) is more accurate than delay(1).

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)


So far, I've checked all timings and merged changes to master branch of repository https://github.com/ivolkov/AD8555.

Still hope someone will test this library to work with AD8555 chip (not AD8556). Have no idea why it wouldn't do the job but just to be sure.

robtillaart

Looks good!

another tip
Code: [Select]
void AD8555::sendMode(uint8_t value)
{
        sendBit((value >> 1) & 1);
        sendBit(value & 1);
}

void AD8555::sendFunc(uint8_t value)
{
        sendBit((value >> 1) & 1); 
        sendBit(value & 1);
}

void AD8555::sendDummy()
{
        sendBit(1);
        sendBit(0);
}


these can be replaced by one function, reduces the footprint of the library.

Code: [Select]

#define DUMMY 0b00000010

void AD8555::send(uint8_t value)
{
        sendBit((value >> 1) & 1); 
        sendBit(value & 1);
}


Finally you could add a link in the header to this thread so people can discuss the library.
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)


Finally you could add a link in the header to this thread so people can discuss the library.

Good idea.


these can be replaced by one function, reduces the footprint of the library.

Thanks, fixed.

BTW are you using static code analyzer or some other refactoring software?

robtillaart


BTW are you using static code analyzer or some other refactoring software?

No,  an eye for patterns, paper and pen,experience and a lot of trial and error.
I like optimizing SW and the constraints of an Arduino "scream" for SW balanced between functionality and code size and performance.
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Go Up