Files
sics/site_ansto/hardsup/sct_lfprot.c
Douglas Clowes 27e89241cf get it to build
2012-11-27 13:34:05 +11:00

263 lines
5.4 KiB
C

/**
* @brief Protocol handler for LG AG1010 Power generator/supplier
*
* The protocol is to handle the Hexidecimal strings sending and receiving from the device,
* the protocol also calculates the CRC for each data sum sent out
*
* Author: Jing Chen, jgn@ansto.gov.au
*
******************************************************************************************/
#include <errno.h>
#include <ascon.h>
#include <ascon.i>
#include <dynstring.h>
static int dbgprintf(char* fmtstr, ...);
typedef unsigned char BYTE;
BYTE updateCRC8(BYTE data, BYTE previousCrc) {
// Polynomial: x^8 + x^5 + x^4 + 1
BYTE crc = previousCrc;
int b;
for(b = 0; b < 8; b++) {
if((crc ^ data) & 0x01) {
crc = crc ^ 0x18;
crc = crc >> 1;
crc = crc | 0x80;
} else {
crc = crc >> 1;
crc = crc & 0x7f;
}
data = data >> 1;
}
return crc;
}
BYTE char_to_int(char c){
BYTE tmp;
if ('0' <= c && c <= '9') {
tmp = c - '0';
} else if ('a' <= c && c <= 'f') {
tmp = 10 + c - 'a';
} else if ('A' <= c && c <= 'F') {
tmp = 10 + c - 'A';
} else {
printf("Error in string.\n");
return NULL;
}
return tmp;
}
BYTE getHexCode(BYTE startPos, char *str){
BYTE tmp = 0;
tmp = (0x0F & char_to_int(str[startPos])) << 4;
tmp = tmp | (0x0F & char_to_int(str[startPos+1]));
return tmp;
}
/** @brief Send the Hexdecimal string with CRC
*/
int LFGenWriteStart(Ascon *a) {
char *pNewBuffer;
unsigned short bufSize, bufInd;
double now;
// Get real packet information from the buffer
char *curText = GetCharArray(a->wrBuffer);
BYTE HEAD, LEN, CTRL, CRC=0;
HEAD = getHexCode(0, curText);
LEN = getHexCode(2, curText);
// buffer size,
pNewBuffer = (char *)malloc((LEN+2)*sizeof(char));
bufInd=0;
pNewBuffer[bufInd] = HEAD;
bufInd++;
pNewBuffer[bufInd] = LEN;
bufInd++;
CRC = updateCRC8(HEAD, CRC);
CRC = updateCRC8(LEN, CRC);
if(LEN<2){
a->state = AsconIdle;
AsconError(a, "Error Datasum Provided!", 0);
return 0;
} else {
CTRL = getHexCode(4, curText);
pNewBuffer[bufInd] = CTRL;
bufInd++;
CRC = updateCRC8(CTRL, CRC);
if(LEN>2){
int i;
for(i=0; i<LEN-2; i++){
pNewBuffer[bufInd] = getHexCode(bufInd*2, curText);
CRC = updateCRC8(pNewBuffer[bufInd], CRC);
bufInd++;
}
}
}
pNewBuffer[bufInd] = CRC;
bufInd++;
//pNewBuffer[bufSize-1] = '\r';
DynStringClear(a->wrBuffer);
DynStringConcatBytes(a->wrBuffer, pNewBuffer, bufInd);
a->wrPos = 0;
a->state = AsconWriting;
/* if there is only the terminator, do not send it */
if (GetDynStringLength(a->wrBuffer) <= 1) {
a->state = AsconWriteDone;
}
//dbgprintf("HEAD=%02x; LEN=%02x; CTRL=%02x; DATA=%s; CRC=%2x -> %s\n", HEAD, LEN, CTRL, Data, CRC, pNewBuffer);
free(pNewBuffer);
return 1;
}
int LFConcatChar(pDynString self, char chr){
int ret;
char *lfChr[2];
BYTE lfByte = (BYTE)chr;
sprintf(lfChr, "%02x", lfByte);
DynStringConcat(self, lfChr);
return 1;
}
int LFGenReading(Ascon *a)
{
int ret;
char chr=0;
BYTE *lfchar, HEAD, LEN;
//BYTE HEAD, LEN, CTRL, CRC=0, *Data=NULL;
// Read HEAD info
usleep(1000*50);
ret = AsconReadChar(a->fd, &chr);
a->start = DoubleTime();
if(ret<0) {
AsconError(a, "AsconReadChar failed in Head Info reading in LFGenReading:", 0);
//a->state = AsconReadDone;
return 0;
} else {
while (ret>=0) {
if(ret>0) {
HEAD = (BYTE)chr;
if (HEAD==0x96) {
break;
}
}
if (a->timeout > 0) {
if (DoubleTime() - a->start > 0.05) { //a->timeout) {
AsconError(a, "read timeout", 0);
a->state = AsconTimeout;
return 1;
}
}
ret = AsconReadChar(a->fd, &chr);
}
}
// read LEN info
ret = AsconReadChar(a->fd, &chr);
if(ret<0) {
AsconError(a, "AsconReadChar failed in LEN reading in LFGenReading:", 0);
//a->state = AsconReadDone;
return 0;
}
LEN = (BYTE)chr;
if(LEN<2) {
AsconError(a, "Reading Error from the LF AG1010 device, wrong LEN info", 0);
a->state = AsconReadDone;
return 0;
}
lfchar = malloc(sizeof(BYTE)*(LEN+2));
int ind=0;
lfchar[ind] = HEAD; ind++;
lfchar[ind] = LEN; ind++;
// read all other chars
while(ind<LEN+2) {
ret = AsconReadChar(a->fd, &chr);
if (ret < 0) {
AsconError(a, "AsconReadChar failed in LFGenReading:", 0);
//a->state = AsconReadDone;
return 0;
}
lfchar[ind] = (BYTE)chr; ind++;
}
DynStringClear(a->rdBuffer);
int i;
for(i=0; i<ind; i++) {
LFConcatChar(a->rdBuffer, lfchar[i]);
}
a->state = AsconReadDone;
free(lfchar);
//DynStringConcatChar(a->rdBuffer, '\0');
return 1;
}
int LFGenProtHandler(Ascon *a)
{
int ret;
switch(a->state){
case AsconWriteStart:
ret = LFGenWriteStart(a);
return ret;
break;
case AsconReading:
return LFGenReading(a);
break;
default:
return AsconStdHandler(a);
}
}
void AddLFGenProtocol()
{
AsconProtocol *prot = NULL;
prot = calloc(sizeof(AsconProtocol), 1);
prot->name = strdup("lfgen");
prot->init = AsconStdInit;
prot->handler = LFGenProtHandler;
AsconInsertProtocol(prot);
}
#include <stdio.h>
#include <stdarg.h>
static int dbgprintf(char* fmtstr, ...) {
FILE* fp = NULL;
int ret = 0;
fp = fopen("/home/jgn/tmp/lfdbg.txt", "a");
if (fp != NULL) {
va_list ap;
va_start(ap, fmtstr);
ret = vfprintf(fp, fmtstr, ap);
va_end(ap);
fclose(fp);
}
return ret;
}