#include #include "ow.h" #include "owd.h" #include "debug.h" struct owd_pot_llist_struct{ struct owd_pot_llist_struct *next; uint8 owm; uint8 ndev; int start; int stop; int lastValue; int rate; }; typedef struct owd_pot_llist_struct owd_pot_llist; owd_pot_llist *OWD_POT_CHAIN=NULL; int OWD_POT_CLIMB_ACTIVE=0; /** * Configure a single channel of ADC * own - One wire master/chain 0-3 * ndev - # of the ADC in chain * chan - which ADC channel to config a-d corresponds to 0-4 * adc - Configures basic adc options * 0-15 bit 1-16 debth with 2.55V max * 16-32 bit 1-16 debth with 5.1V max * conf - Configures misc stuff, use 0 if you dont know what to do. * Bit 0: Enable Low Alarm * Bit 1: Enable High Alarm * Bit 2: Set High Alarm Flag * Bit 3: Set Low Alarm flag * Bit 4: Enable Output contoll * Bit 5: Turn On/Off output * return * -1 improper config * 0 ow error * 1 sucess **/ int OWD_ADCConfChan(uint8 owm, uint8 ndev, unsigned int chan, unsigned int adc, unsigned int conf){ uint8 confA=0, confB=0, i=0, rb=0; uint32 buf=0; //used to send of data to checksummer uint16 checksum=0; if(adc<=14){ confA=adc+1; }else if(adc==15){ confA=0; }else if(adc>=16 && adc<=31){ confA+=adc-15; confB=1; }else if(adc==32){ confA=0; confB=1; }else{ return -1; } confA |= (conf&48)<<2; confB |= (conf&15)<<2; confA &= 255-32-16; confB &= 255-128-64-2; if(chan>3) return -1; chan=(chan*2)+8; if(!OW_invoke(owm, DS2450_FAM, ndev)){ return 0; } //Select address to write to OW_command(owm, DS2482_OW_WRITE_BYTE, DS2450_WRITE_MEM); OW_command(owm, DS2482_OW_WRITE_BYTE, chan); OW_command(owm, DS2482_OW_WRITE_BYTE, 0); //Send first config byte OW_command(owm, DS2482_OW_WRITE_BYTE, confA ); //Check data buf=DS2450_WRITE_MEM<<24|chan<<16|0<<8|confA; if(!OW_crc16(owm, ndev, (char*)&buf, 4)){ return 0; } if(confA!=OW_getByte(owm)){ return 0; } //Send second config byte OW_command(owm, DS2482_OW_WRITE_BYTE, confB); buf=(chan+1)<<8|confA; if(!OW_crc16(owm, ndev, (char*)&buf, 2)){ return 0; } if(confB!=OW_getByte(owm)){ return 0; } if(!OW_invoke(owm, DS2450_FAM, ndev)){ return 0; } //Keep analog circuit permamently active (page 6 of DS2450 docs) OW_command(owm, DS2482_OW_WRITE_BYTE, DS2450_WRITE_MEM ); OW_command(owm, DS2482_OW_WRITE_BYTE, 0x1c); OW_command(owm, DS2482_OW_WRITE_BYTE, 0x00); OW_command(owm, DS2482_OW_WRITE_BYTE, 0x40); buf=DS2450_WRITE_MEM<<24|0x1C0040; if(!OW_crc16(owm, ndev, (char*)&buf, 4)){ return 0; } if(0x40!=OW_getByte(owm)){ return 0; } return 1; } /** * Set ADC redout registers to 0 and digitize all channels * own - One wire master/chain 0-3 * ndev - # of the ADC in chain * return * 0 ow error * 1 sucess **/ int OWD_ADCConv(uint8 owm, uint8 ndev){ if(!OW_invoke(owm, DS2450_FAM, ndev)){ return 0; } uint32 buf=0; //used to send of data to checksummer OW_command(owm, DS2482_OW_WRITE_BYTE, DS2450_CONVERT); OW_command(owm, DS2482_OW_WRITE_BYTE, 0x0F); OW_command(owm, DS2482_OW_WRITE_BYTE, 0x55); buf=DS2450_CONVERT<<16|0x0F55; if(!OW_crc16(owm, ndev, (char *)&buf, 3)){ return 0; } return 1; } /** * Reads in all adc channels * own - One wire master/chain 0-3 * ndev - # of the ADC in chain * chA - Where to write results from channel A * chB - Where to write results from channel B * chC - Where to write results from channel C * chD - Where to write results from channel D **/ int OWD_ADCReadAll(uint8 owm, uint8 ndev, unsigned int *chA, unsigned int *chB, unsigned int *chC, unsigned int *chD){ uint8 * buf=malloc(16*3*sizeof(uint8)); //3 readouts max uint8 * ptr=buf; if(buf==NULL){ return -1; } if(!OW_invoke(owm, DS2450_FAM, ndev)){ return 0; } OW_command(owm, DS2482_OW_WRITE_BYTE, DS2450_READ_MEM ); OW_command(owm, DS2482_OW_WRITE_BYTE, 0x00); OW_command(owm, DS2482_OW_WRITE_BYTE, 0x00); *chA=OW_getByte(owm)|OW_getByte(owm)<<8; *chB=OW_getByte(owm)|OW_getByte(owm)<<8; *chC=OW_getByte(owm)|OW_getByte(owm)<<8; *chD=OW_getByte(owm)|OW_getByte(owm)<<8; *ptr=DS2450_READ_MEM; ptr++; *ptr=0; ptr++; *ptr=0; ptr++; *ptr=*chA>>8; ptr++; *ptr|=*chA&0xff; if(!OW_crc16(owm, ndev, (char *)&buf, 5)){ return 0; } ptr=buf; *ptr=*chB>>8; ptr++; *ptr|=*chB&0xff; ptr++; *ptr=*chC>>8; ptr++; *ptr|=*chC&0xff; ptr++; *ptr=*chD>>8; ptr++; *ptr|=*chD&0xff; ptr++; if(!OW_crc16(owm, ndev, (char *)&buf, 6)){ return 0; } free(buf); return 1; } /** * Sets Charge pump state of POT * own - One wire master/chain 0-3 * ndev - # of the ADC in chain * cpc - Charge pumpt state * 0 disable charge pump (choose if dont know) * 1 enable charge pump * return * -1 improper config * 0 ow error * 1 sucess **/ int OWD_POTConf(uint8 owm, uint8 ndev, uint8 cpc){ if(cpc==0){ cpc=0x0C; }else if(cpc==1){ cpc=0x4C; }else{ return -1; } if(!OW_invoke(owm, DS2890_FAM, ndev)){ return 0; } OW_command(owm, DS2482_OW_WRITE_BYTE, DS2890_WRITE_CTL_REG); OW_command(owm, DS2482_OW_WRITE_BYTE, cpc); if(cpc!=OW_getByte(owm)){ return 0; } OW_command(owm, DS2482_OW_WRITE_BYTE, DS2890_RELEASE_CODE); if(OW_getByte(owm)!=0){ return 0; } return 1; } /** * Sets and verifies the wiper position of POT * own - One wire master/chain 0-3 * ndev - # of the POT in chain * wp - wiper position 0-255 **/ int OWD_POTset(uint8 owm, uint8 ndev, uint8 wp){ if(!OW_invoke(owm, DS2890_FAM, ndev)){ return 0; } OW_command(owm, DS2482_OW_WRITE_BYTE, DS2890_WRITE_POS); OW_command(owm, DS2482_OW_WRITE_BYTE, wp); if(wp!=OW_getByte(owm)){ return 0; } OW_command(owm, DS2482_OW_WRITE_BYTE, DS2890_RELEASE_CODE); if(OW_getByte(owm)!=0){ return 0; } return 1; } /** * Reads wiper position of POT * own - One wire master/chain 0-3 * ndev - # of the POT in chain * returns 0 on error, else state of pot **/ int OWD_POTget(uint8 owm, uint8 ndev){ if(!OW_invoke(owm, DS2890_FAM, ndev)){ return 0; } OW_command(owm, DS2482_OW_WRITE_BYTE, DS2890_READ_POS ); OW_getByte(owm); //Whoop-dee-doo we get the config back.. we dont care about it return OW_getByte(owm); } /** * Increment wiper position of POT * own - One wire master/chain 0-3 * ndev - # of the POT in chain * returns -1 on error, else state of pot **/ int OWD_POTincr(uint8 owm, uint8 ndev){ if(!OW_invoke(owm, DS2890_FAM, ndev)){ return -1; } if(OW_command(owm, DS2482_OW_WRITE_BYTE, DS2890_INCR )){ return OW_getByte(owm); }else{ return -1; } } /** * Decrement wiper position of POT * own - One wire master/chain 0-3 * ndev - # of the POT in chain * returns -1 on error, else state of pot **/ int OWD_POTdecr(uint8 owm, uint8 ndev){ if(!OW_invoke(owm, DS2890_FAM, ndev)){ return -1; } if(OW_command(owm, DS2482_OW_WRITE_BYTE, DS2890_DECR )){ return OW_getByte(owm); }else{ return -1; } } void OWD_POTClimbPurge(){ owd_pot_llist *potPtr; if(OWD_POT_CHAIN==NULL){ return; } while(OWD_POT_CHAIN!=NULL){ potPtr=OWD_POT_CHAIN; OWD_POT_CHAIN=OWD_POT_CHAIN->next; free(potPtr); } } int OWD_POTClimbAdd(uint8 owm, uint8 ndev, uint8 start, uint8 stop, uint8 rate){ owd_pot_llist *potPtr; if(OWD_POT_CHAIN==NULL){ OWD_POT_CHAIN=malloc(sizeof(owd_pot_llist)); if(OWD_POT_CHAIN==NULL){ DBG_PRINTL("OWD_POTClimbAdd: Malloc failed 0.\n"); return 0; } potPtr=OWD_POT_CHAIN; potPtr->next=NULL; }else{ potPtr=malloc(sizeof(owd_pot_llist)); if(potPtr=NULL){ DBG_PRINTL("OWD_POTClimbAdd: Malloc failed 1.\n"); return 0; } potPtr->next=OWD_POT_CHAIN; OWD_POT_CHAIN=potPtr; } potPtr->owm=owm; potPtr->ndev=ndev; potPtr->start=start; potPtr->stop=stop; potPtr->rate=rate; potPtr->lastValue=-1; return 1; } int OWD_POTClimbInit(){ int count=0; owd_pot_llist *potPtr; if(OWD_POT_CLIMB_ACTIVE>0){ DBG_PRINTL("WD_POTClimbStart: Climb is still/already active.\n"); return 0; } if(OWD_POT_CHAIN==NULL){ DBG_PRINTL("WD_POTClimbStart: Chain is empty, add some devices.\n"); return 0; } potPtr=OWD_POT_CHAIN; while(potPtr!=NULL){ if(!OWD_POTset(potPtr->owm, potPtr->ndev, potPtr->start)){ potPtr->lastValue=potPtr->stop; DBG_PRINTF("WD_POTClimbStart: OWD_POTset failed, %u %u\n", potPtr->owm, potPtr->ndev); return 0; } potPtr->lastValue=potPtr->start; potPtr=potPtr->next; count++; } return count; } void OWD_POTClimbStop(){ OWD_POT_CLIMB_ACTIVE=0; } void OWD_POTClimbStart(){ OWD_POT_CLIMB_ACTIVE=1; } int OWD_POTClimbCount(){ return OWD_POT_CLIMB_ACTIVE; } void OWD_POTClimbPrintAll(){ owd_pot_llist *potPtr; potPtr=OWD_POT_CHAIN; while(potPtr!=NULL){ DBG_PRINTF("owm: %u, ndev: %u, start: %d, stop: %d, lastValue: %d, rate: %d\n", potPtr->owm, potPtr->ndev, potPtr->start, potPtr->stop, potPtr->lastValue, potPtr->rate); potPtr=potPtr->next; } } void OWD_POTClimbLoop(){ owd_pot_llist *potPtr; int count=0; int i; if(OWD_POT_CLIMB_ACTIVE==0){ return; } if(OWD_POT_CHAIN==NULL){ DBG_PRINTL("WD_POTClimbStart: Chain is empty, add some devices.\n"); return; } potPtr=OWD_POT_CHAIN; while(potPtr!=NULL){ if(potPtr->lastValue>=0){ for(i=0; irate && potPtr->lastValue!=potPtr->stop; i++){ if(potPtr->lastValuestop){ potPtr->lastValue=OWD_POTincr(potPtr->owm, potPtr->ndev); //count++; }else if(potPtr->lastValue>potPtr->stop){ potPtr->lastValue=OWD_POTdecr(potPtr->owm, potPtr->ndev); //count++; } } if(i!=0) count++; } potPtr=potPtr->next; } OWD_POT_CLIMB_ACTIVE=count; } /** * Configures thermometers digitization depth * own - One wire master/chain 0-3 * ndev - # of the thermometer in chain * conf - digitization depth * 0-4 is 9-12 bit respectively **/ int OWD_THMconf(uint8 owm, uint8 ndev, uint8 conf){ if(!OW_invoke(owm, DS18B20_FAM, ndev)){ return 0; } if(conf>4){ return -1; } OW_command(owm, DS2482_OW_WRITE_BYTE, DS18B20_WRITE_SCRATCH); OW_command(owm, DS2482_OW_WRITE_BYTE, 0x00); OW_command(owm, DS2482_OW_WRITE_BYTE, 0x00); OW_command(owm, DS2482_OW_WRITE_BYTE, conf); return 1; } /** * Starts digitization for thermometer: 9bit take 94ms, and 12bit takes 750ms * own - One wire master/chain 0-3 * ndev - # of the thermometer in chain **/ int OWD_THMconv(uint8 owm, uint8 ndev){ if(!OW_invoke(owm, DS18B20_FAM, ndev)){ return 0; } OW_command(owm, DS2482_OW_WRITE_BYTE, DS18B20_CONVERT_T); return 1; } /** * Reads out digitized temperature in .0001K * own - One wire master/chain 0-3 * ndev - # of the thermometer in chain **/ int OWD_THMget(uint8 owm, uint8 ndev){ uint16 tmp; int ret=0; int mult=1; if(!OW_invoke(owm, DS18B20_FAM, ndev)){ return 0; } OW_command(owm, DS2482_OW_WRITE_BYTE, DS18B20_READ_SCRATCH); tmp=OW_getByte(owm); tmp|=OW_getByte(owm)<<8; if(tmp>1024){ mult=-1; tmp^=0xffff; } ret=(tmp>>4)+273; ret*=10000; if(tmp&1) ret+=625; if(tmp&2) ret+=1250; if(tmp&4) ret+=2500; if(tmp&8) ret+=5000; ret*=mult; return ret; } /** * reads PIO state of switch and returns it. on failure returns 0 **/ int OWD_SWCHget(uint8 owm, uint8 ndev){ uint8 buf=0; if(!OW_invoke(owm, DS2413_FAM, ndev)){ DBG_PRINTL("OWD_SWCHget: Invoking device failed.\n"); return -1; } if(!OW_command(owm, DS2482_OW_WRITE_BYTE, DS2413_PIO_READ)){ DBG_PRINTL("OWD_SWCHget: Failed sending command.\n"); return -1; } buf=OW_getByte(owm); if(~(buf >> 4) == (buf & 0x0f)){ return (buf & 0x0F); }else{ DBG_PRINTL("OWD_SWCHget: Read receive error\n"); return -1; } } /** * reads PIO state of switch and returns it. on failure returns 0 **/ int OWD_SWCHset(uint8 owm, uint8 ndev, uint8 pinA, uint8 pinB){ uint8 buf=0; if(pinA>1 || pinB>1){ DBG_PRINTL("OWD_SWCHset: Invoked with invalid pin states.\n"); return -1; } if(!OW_invoke(owm, DS2413_FAM, ndev)){ DBG_PRINTL("OWD_SWCHset: Invoking device failed.\n"); return 0; } if(!OW_command(owm, DS2482_OW_WRITE_BYTE, DS2413_PIO_WRITE)){ DBG_PRINTL("OWD_SWCHset: Failed sending command.\n"); return 0; } buf= pinA | (pinB<<1) | 0xfc; if(!OW_command(owm, DS2482_OW_WRITE_BYTE, buf)){ DBG_PRINTL("OWD_SWCHset: Failed writing switch state\n"); return 0; } if(!OW_command(owm, DS2482_OW_WRITE_BYTE, ~buf)){ DBG_PRINTL("OWD_SWCHset: Failed writing switch complement\n"); return 0; } if(OW_getByte(owm)!=0xAA){ DBG_PRINTL("OWD_SWCHset: Ack byte read failed\n"); return 0; } //More confirmation can be done here but whats the point? }