440 lines
7.6 KiB
C
440 lines
7.6 KiB
C
/*
|
|
* Copyright (C) Roland Jax 2012-2013 <roland.jax@liwest.at>
|
|
* crc calculations from http://www.mikrocontroller.net/topic/75698
|
|
*
|
|
* This file is part of ebusd.
|
|
*
|
|
* ebusd is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* ebusd is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with ebusd. If not, see http://www.gnu.org/licenses/.
|
|
*/
|
|
|
|
/**
|
|
* @file ebus-decode.c
|
|
* @brief ebus decode functions
|
|
* @author roland.jax@liwest.at
|
|
* @version 0.1
|
|
*/
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif /* HAVE_CONFIG_H */
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
|
|
#include "ebus-decode.h"
|
|
|
|
|
|
|
|
const char *days[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
|
|
|
|
|
|
|
|
int
|
|
eb_htoi(const char *buf)
|
|
{
|
|
int ret;
|
|
ret = -1;
|
|
|
|
if (isxdigit(*buf)) {
|
|
if (isalpha(*buf))
|
|
ret = 55;
|
|
else
|
|
ret = 48;
|
|
|
|
ret = toupper(*buf) - ret;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
void
|
|
eb_esc(unsigned char *buf, int *buflen)
|
|
{
|
|
unsigned char tmp[BUS_DEVICE_BUFSIZE];
|
|
int tmplen, i;
|
|
|
|
memset(tmp, '\0', sizeof(tmp));
|
|
i = 0;
|
|
tmplen = 0;
|
|
|
|
while (i < *buflen) {
|
|
|
|
if (buf[i] == EBUS_SYN) {
|
|
tmp[tmplen] = EBUS_SYN_ESC_A9;
|
|
tmplen++;
|
|
tmp[tmplen] = EBUS_SYN_ESC_01;
|
|
tmplen++;
|
|
} else if (buf[i] == EBUS_SYN_ESC_A9) {
|
|
tmp[tmplen] = EBUS_SYN_ESC_A9;
|
|
tmplen++;
|
|
tmp[tmplen] = EBUS_SYN_ESC_00;
|
|
tmplen++;
|
|
} else {
|
|
tmp[tmplen] = buf[i];
|
|
tmplen++;
|
|
}
|
|
|
|
i++;
|
|
}
|
|
|
|
memset(buf, '\0', sizeof(buf));
|
|
for (i = 0; i < tmplen; i++)
|
|
buf[i] = tmp[i];
|
|
|
|
*buflen = tmplen;
|
|
}
|
|
|
|
void
|
|
eb_unesc(unsigned char *buf, int *buflen)
|
|
{
|
|
unsigned char tmp[BUS_DEVICE_BUFSIZE];
|
|
int tmplen, i, found;
|
|
|
|
memset(tmp, '\0', sizeof(tmp));
|
|
i = 0;
|
|
tmplen = 0;
|
|
found = 0;
|
|
|
|
while (i < *buflen) {
|
|
|
|
if (buf[i] == EBUS_SYN_ESC_A9) {
|
|
found = 1;
|
|
} else if (found == 1) {
|
|
if (buf[i] == EBUS_SYN_ESC_01) {
|
|
tmp[tmplen] = EBUS_SYN;
|
|
tmplen++;
|
|
} else {
|
|
tmp[tmplen] = EBUS_SYN_ESC_A9;
|
|
tmplen++;
|
|
}
|
|
|
|
found = 0;
|
|
} else {
|
|
tmp[tmplen] = buf[i];
|
|
tmplen++;
|
|
}
|
|
|
|
i++;
|
|
}
|
|
|
|
memset(buf, '\0', sizeof(buf));
|
|
for (i = 0; i < tmplen; i++)
|
|
buf[i] = tmp[i];
|
|
|
|
*buflen = tmplen;
|
|
}
|
|
|
|
|
|
|
|
int
|
|
eb_day_to_str(unsigned char day, char *tgt)
|
|
{
|
|
int dd;
|
|
|
|
if ((day & 0x0F) >= 0x00 && (day & 0x0F) <= 0x06) {
|
|
eb_bcd_to_int(day, &dd);
|
|
sprintf(tgt, "%s", days[dd]);
|
|
} else {
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int
|
|
eb_dat_to_str(unsigned char dd, unsigned char mm, unsigned char yy, char *tgt)
|
|
{
|
|
if ((dd & 0x7F) >= 0x00 && (dd & 0x7F) <= 0x1F &&
|
|
(mm & 0x7F) >= 0x00 && (mm & 0x7F) <= 0x0C &&
|
|
(yy & 0x7F) >= 0x00 && (yy & 0x7F) <= 0x63 )
|
|
sprintf(tgt, "%02d.%02d.%04d", dd, mm, yy + 2000);
|
|
else
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
eb_str_to_dat(int dd, int mm, int yy, unsigned char *tgt)
|
|
{
|
|
if (yy > 2000)
|
|
yy -= 2000;
|
|
|
|
if (dd >= 0 && dd <= 31 &&
|
|
mm >= 0 && mm <= 12 &&
|
|
yy >= 0 && yy <= 99 )
|
|
sprintf((char *) tgt, "%02x%02x%02x", dd, mm, yy);
|
|
|
|
else
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int
|
|
eb_tim_to_str(unsigned char hh, unsigned char mm, unsigned char ss, char *tgt)
|
|
{
|
|
if ((hh & 0x7F) >= 0x00 && (hh & 0x7F) <= 0x17 &&
|
|
(mm & 0x7F) >= 0x00 && (mm & 0x7F) <= 0x3B &&
|
|
(ss & 0x7F) >= 0x00 && (ss & 0x7F) <= 0x3B )
|
|
sprintf(tgt, "%02d:%02d:%02d", hh, mm, ss);
|
|
else
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
eb_str_to_tim(int hh, int mm, int ss, unsigned char *tgt)
|
|
{
|
|
|
|
if (hh >= 0 && hh <= 23 &&
|
|
mm >= 0 && mm <= 59 &&
|
|
ss >= 0 && ss <= 59 )
|
|
sprintf((char *) tgt, "%02x%02x%02x", hh, mm, ss);
|
|
|
|
else
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int
|
|
eb_bcd_to_int(unsigned char src, int *tgt)
|
|
{
|
|
if ((src & 0x0F) > 0x09 || ((src >> 4) & 0x0F) > 0x09) {
|
|
*tgt = (int) (0xFF);
|
|
return 0;
|
|
} else {
|
|
*tgt = (int) ( ( ((src & 0xF0) >> 4) * 10) + (src & 0x0F) );
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
int
|
|
eb_int_to_bcd(int src, unsigned char *tgt)
|
|
{
|
|
if (src > 99) {
|
|
*tgt = (unsigned char) (0xFF);
|
|
return 0;
|
|
} else {
|
|
*tgt = (unsigned char) ( ((src / 10) << 4) | (src % 10) );
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
int
|
|
eb_d1b_to_int(unsigned char src, int *tgt)
|
|
{
|
|
if ((src & 0x80) == 0x80) {
|
|
*tgt = (int) (- ( ((unsigned char) (~ src)) + 1) );
|
|
|
|
if (*tgt == -0x80)
|
|
return 0;
|
|
else
|
|
return -1;
|
|
|
|
} else {
|
|
*tgt = (int) (src);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
int
|
|
eb_int_to_d1b(int src, unsigned char *tgt)
|
|
{
|
|
if (src < -127 || src > 127) {
|
|
*tgt = (unsigned char) (0x80);
|
|
return 0;
|
|
} else {
|
|
if (src >= 0) {
|
|
*tgt = (unsigned char) (src);
|
|
return 1;
|
|
} else {
|
|
*tgt = (unsigned char) (- (~ (src - 1) ) );
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
int
|
|
eb_d1c_to_float(unsigned char src, float *tgt)
|
|
{
|
|
if (src > 0xC8) {
|
|
*tgt = (float) (0xFF);
|
|
return 0;
|
|
} else {
|
|
*tgt = (float) (src / 2.0);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
int
|
|
eb_float_to_d1c(float src, unsigned char *tgt)
|
|
{
|
|
if (src < 0.0 || src > 100.0) {
|
|
*tgt = (unsigned char) (0xFF);
|
|
return 0;
|
|
} else {
|
|
*tgt = (unsigned char) (src * 2.0);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
int
|
|
eb_d2b_to_float(unsigned char src_lsb, unsigned char src_msb, float *tgt)
|
|
{
|
|
if ((src_msb & 0x80) == 0x80) {
|
|
*tgt = (float)
|
|
(- ( ((unsigned char) (~ src_msb)) +
|
|
( ( ((unsigned char) (~ src_lsb)) + 1) / 256.0) ) );
|
|
|
|
if (src_msb == 0x80 && src_lsb == 0x00)
|
|
return 0;
|
|
else
|
|
return -1;
|
|
|
|
} else {
|
|
*tgt = (float) (src_msb + (src_lsb / 256.0));
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
int
|
|
eb_float_to_d2b(float src, unsigned char *tgt_lsb, unsigned char *tgt_msb)
|
|
{
|
|
if (src < -127.999 || src > 127.999) {
|
|
*tgt_msb = (unsigned char) (0x80);
|
|
*tgt_lsb = (unsigned char) (0x00);
|
|
return 0;
|
|
} else {
|
|
*tgt_lsb = (unsigned char) ((src - ((unsigned char) src)) * 256.0);
|
|
|
|
if (src < 0.0 && *tgt_lsb != 0x00)
|
|
*tgt_msb = (unsigned char) (src - 1);
|
|
else
|
|
*tgt_msb = (unsigned char) (src);
|
|
|
|
if (src >= 0.0)
|
|
return 1;
|
|
else
|
|
return -1;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
int
|
|
eb_d2c_to_float(unsigned char src_lsb, unsigned char src_msb, float *tgt)
|
|
{
|
|
if ((src_msb & 0x80) == 0x80) {
|
|
*tgt = (float)
|
|
(- ( ( ( ((unsigned char) (~ src_msb)) * 16.0) ) +
|
|
( ( ((unsigned char) (~ src_lsb)) & 0xF0) >> 4) +
|
|
( ( ( ((unsigned char) (~ src_lsb)) & 0x0F) +1 ) / 16.0) ) );
|
|
|
|
if (src_msb == 0x80 && src_lsb == 0x00)
|
|
return 0;
|
|
else
|
|
return -1;
|
|
|
|
} else {
|
|
*tgt = (float) ( (src_msb * 16.0) + ((src_lsb & 0xF0) >> 4) +
|
|
((src_lsb & 0x0F) / 16.0) );
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
int
|
|
eb_float_to_d2c(float src, unsigned char *tgt_lsb, unsigned char *tgt_msb)
|
|
{
|
|
if (src < -2047.999 || src > 2047.999) {
|
|
*tgt_msb = (unsigned char) (0x80);
|
|
*tgt_lsb = (unsigned char) (0x00);
|
|
return 0;
|
|
} else {
|
|
*tgt_lsb =
|
|
( ((unsigned char) ( ((unsigned char) src) % 16) << 4) +
|
|
((unsigned char) ( (src - ((unsigned char) src)) * 16.0)) );
|
|
|
|
if (src < 0.0 && *tgt_lsb != 0x00)
|
|
*tgt_msb = (unsigned char) ((src / 16.0) - 1);
|
|
else
|
|
*tgt_msb = (unsigned char) (src / 16.0);
|
|
|
|
if (src >= 0.0)
|
|
return 1;
|
|
else
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
unsigned char
|
|
eb_calc_crc_byte(unsigned char byte, unsigned char init_crc)
|
|
{
|
|
unsigned char crc, polynom;
|
|
int i;
|
|
|
|
crc = init_crc;
|
|
|
|
for (i = 0; i < 8; i++) {
|
|
|
|
if (crc & 0x80)
|
|
polynom = (unsigned char) 0x9B;
|
|
else
|
|
polynom = (unsigned char) 0;
|
|
|
|
crc = (unsigned char) ((crc & ~0x80) << 1);
|
|
|
|
if (byte & 0x80)
|
|
crc = (unsigned char) (crc | 1);
|
|
|
|
crc = (unsigned char) (crc ^ polynom);
|
|
byte = (unsigned char) (byte << 1);
|
|
}
|
|
|
|
return crc;
|
|
}
|
|
|
|
unsigned char
|
|
eb_calc_crc(const unsigned char *buf, int buflen)
|
|
{
|
|
int i;
|
|
unsigned char crc = 0;
|
|
|
|
for (i = 0 ; i < buflen ; i++, buf++)
|
|
crc = eb_calc_crc_byte(*buf, crc);
|
|
|
|
return crc;
|
|
}
|
|
|