aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMDC Service <michael.schmid@mdc-service.de>2022-05-26 10:10:35 +0200
committerGitHub <noreply@github.com>2022-05-26 10:10:35 +0200
commit16d74f96ac773e9d3cd5b5f2a5a5714d509dfbf9 (patch)
treee6305d95d03d36a9a9f35eb791fd6d6581201dd0
parent0cebcef38058a3c0be9d05f0369580be66ba0e00 (diff)
moved MU80 from libs to drivers
-rw-r--r--software/drivers/MU80X.cpp587
-rw-r--r--software/drivers/MU80X.h111
2 files changed, 698 insertions, 0 deletions
diff --git a/software/drivers/MU80X.cpp b/software/drivers/MU80X.cpp
new file mode 100644
index 0000000..143ffc2
--- /dev/null
+++ b/software/drivers/MU80X.cpp
@@ -0,0 +1,587 @@
+/*
+ * MU80X.cpp
+ *
+ * Created on: 15.07.2021
+ * Author: steffen
+ * SPDX-FileCopyrightText: 2022 MDC Service <info@mdc-service.de>
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+/**
+* driver for Chafon MU80X (MU801, MU804, MU808, MU816) Rain UHF RFID reader/writer
+*/
+
+#include "MU80X.h"
+
+//#define DEBUG
+#ifdef ESP32
+
+/**
+ * MU80X constructor
+ *
+ * @param fh device handle
+ */
+
+MU80X::MU80X(int fh) {
+ ProtStatus = 0;
+ ConnectionStatus=0;
+ TagsInBuffer=0;
+ TagsSeen=0;
+ _devid = 0xFF;
+
+ _devh = fh;
+
+ int res = iGetReaderInformation(_devid);
+ if (res >= 0) {
+// printf("RDR Info:%d\n",res);
+// DumpBuffer(RecvBuf,res);
+// fflush (stdout);
+ _devid = RecvBuf[1];
+ }
+}
+#else
+
+/**
+ * MU80X constructor
+ *
+ * @param dev device as character
+ * @param baud baud rate for serial communication
+ */
+
+
+MU80X::MU80X(const char *dev, const uint16_t baud) {
+ struct termios t1, t2;
+
+ ProtStatus = 0;
+ _devid = 0xFF;
+
+ int bd = B115200;
+ if (baud == 57600)
+ bd = B57600;
+
+ _devh = open(dev, O_RDWR | O_NONBLOCK);
+ if (_devh < 0) {
+ fprintf(stderr, "Unable to open serial device %s", dev);
+ } else {
+
+ tcgetattr(_devh, &t1);
+ tcgetattr(_devh, &t2);
+ cfmakeraw(&t1);
+
+ t1.c_cflag = (CLOCAL | CS8 | CREAD);
+ cfsetspeed(&t1, bd);
+ t1.c_cc[VMIN] = 0;
+ t1.c_cc[VTIME] = 0;
+ tcsetattr(_devh, TCSADRAIN, &t1);
+
+ int res = iGetReaderInformation(_devid);
+ if (res >= 0) {
+ fflush (stdout);
+ _devid = RecvBuf[1];
+ }
+ }
+
+}
+#endif
+
+/**
+ * MU80X destructor
+ *
+ */
+
+MU80X::~MU80X(void) {
+#ifdef ESP32
+
+#else
+ if (_devh > 0)
+ close(_devh);
+#endif
+}
+// internal
+
+/**
+ * MU80X DumpBuffer
+ *
+ * @param buf buffer to dump
+ * @param len length of buffer
+ */
+void MU80X::DumpBuffer(unsigned char *buf, int len) {
+ int i, c;
+ char *lb = (char*) buf;
+ for (i = 0; i < len; i++) {
+ if (i % 32 == 0)
+ printf("\n");
+ c = (char) *lb++;
+ printf("%02X ", (unsigned char) c);
+ if (c > 32)
+ printf(" %c ", c);
+ else
+ printf(" ");
+
+ }
+ printf("\n");
+}
+
+/**
+ * MU80X PrintTag
+ *
+ * @param tag tag structure
+ */
+void MU80X::PrintTag(Tag_t tag) {
+ int i;
+ for (i = 0; i < 12; i++) {
+ printf("%02X ", tag.b[i]);
+ }
+ printf("Ant:%d RSSI:%d Count:%d ", tag.ant, tag.rssi, tag.count);
+ printf("\n");
+}
+
+/**
+ * MU80X _DecodeBuffer
+ *
+ * @param todecode maximal length to decode
+ * @param start start position to decode
+ * @param buf char buffer
+ * @param tagbuf pointer to Tag_t structure
+ * @returns position after decoding
+ */
+int MU80X::_DecodeBuffer(int todecode, int start, unsigned char *buf,
+ Tag_t *tagbuf) {
+ int i;
+ uint8_t len, ant, rssi, count;
+ for (i = start; i < start + todecode; i++) {
+// DumpBuffer(buf,s);
+ ant = *buf;
+ buf++;
+ len = *buf;
+ buf++;
+ tagbuf[i].ant = ant;
+#ifdef DEBUG
+ printf("Ant: %d Len: %d",ant,len);
+#endif
+ if (len == 8) {
+ tagbuf[i].b[0] = 0;
+ tagbuf[i].b[1] = 0;
+ tagbuf[i].b[2] = 0;
+ tagbuf[i].b[3] = 0;
+ memcpy(&tagbuf[i].b[4], buf, len);
+ } else if (len == 12) {
+ memcpy(&tagbuf[i].b[0], buf, len);
+ } else {
+ fprintf(stderr, "Unknown Taglength:%d :\n", len);
+ }
+ buf += len;
+ rssi = *buf;
+ buf++;
+ count = *buf;
+ buf++;
+ tagbuf[i].rssi = rssi;
+ tagbuf[i].count = count;
+#ifdef DEBUG
+ printf("Ant: %d Len: %d\n",ant,len);
+// PrintTag(tagbuf[i]);
+#endif
+
+ }
+ return i - start;
+}
+
+#define PRESET_VALUE 0xFFFF
+#define POLYNOMIAL 0x8408
+
+/**
+ * MU80X _ui16CalculateCrc
+ *
+ * @param data data pointer
+ * @param len length of data
+ * @returns CRC calculated from data
+ */
+
+uint16_t MU80X::_ui16CalculateCrc(unsigned char *data, unsigned char len) {
+
+ unsigned char ucI, ucJ;
+ uint16_t uiCrcValue = PRESET_VALUE;
+ for (ucI = 0; ucI < len; ucI++) {
+ uiCrcValue = uiCrcValue ^ *(data + ucI);
+ for (ucJ = 0; ucJ < 8; ucJ++) {
+ if (uiCrcValue & 0x0001) {
+ uiCrcValue = (uiCrcValue >> 1) ^ POLYNOMIAL;
+ } else {
+ uiCrcValue = (uiCrcValue >> 1);
+ }
+ }
+ }
+ return uiCrcValue;
+}
+
+/**
+ * MU80X serial_read
+ *
+ * @param fh device handle.
+ * @param buf buffer to read in.
+ * @returns number of bytes read
+ */
+int MU80X::serial_read(int fh, unsigned char *buf) {
+#ifdef ESP32
+ return (uart_read_bytes(fh, buf, 1, 1));
+#else
+ return (read(fh,buf,1));
+#endif
+}
+
+/**
+ * MU80X serial_write
+ *
+ * @param fh device handle.
+ * @param buf buffer to write to.
+ * @param len number of bytes to write.
+ * @returns number of bytes written.
+ */
+int MU80X::serial_write(int fh, unsigned char *buf, int len) {
+#ifdef ESP32
+ return (uart_write_bytes(fh, buf, len));
+#else
+ return(write(fh,buf,len));
+#endif
+}
+
+/**
+ * MU80X iReadProt
+ *
+ * @param ms
+ * @returns number of bytes written.
+ */
+// low level read and write
+int MU80X::iReadProt(int ms) {
+ int cnt = ms;
+ int cc = 0;
+ uint8_t len = 0;
+ int i;
+ while (cnt > 0) {
+ if ((cc == 0) & (serial_read(_devh, &RecvBuf[0]) == 1)) {
+ len = (uint8_t) RecvBuf[0];
+#ifdef DEBUG
+ printf("\nNeed to receive:%d\n", len+1);
+#endif
+ fflush (stdout);
+ cc = 1;
+ cnt = ms;
+ i = 1;
+ while (i <= len) {
+ if (serial_read(_devh, &RecvBuf[i]) == 1) {
+ i++;
+ cnt = ms;
+ } else {
+// printf(" X ");fflush(stdout);
+ cnt--;
+ if (cnt == 0)
+ return ERR_NOANSWER;
+#ifdef ESP32
+ vTaskDelay(1);
+#else
+ usleep(1000);
+#endif
+ }
+ }
+#ifdef DEBUG
+ printf("Received:%d\n", len+1);
+ fflush(stdout);
+#endif
+ return len + 1;
+ }
+
+ cnt--;
+#ifdef ESP32
+ vTaskDelay(1);
+#else
+ usleep(1000);
+#endif
+ }
+ return -1;
+}
+
+/**
+ * MU80X iSendProt
+ *
+ * @param len number of bytes to write.
+ * @param adr address to send.
+ * @param cmd command to send.
+ * @param data data to send
+ * @returns number of bytes written, or error code.
+ */
+int MU80X::iSendProt(uint8_t len, uint8_t adr, uint8_t cmd,
+ unsigned char *data) {
+ int res = 0;
+ uint16_t CRC = 0;
+ SendBuf[0] = len + 4;
+ SendBuf[1] = adr;
+ SendBuf[2] = cmd;
+ memcpy(&SendBuf[3], data, len);
+ CRC = _ui16CalculateCrc(SendBuf, len + 3);
+ SendBuf[3 + len] = CRC & 0xFF;
+ SendBuf[4 + len] = CRC >> 8;
+#ifdef DEBUG
+ printf("Send:");
+ DumpBuffer(SendBuf, len + 5);
+#endif
+ res = serial_write(_devh, (unsigned char *)SendBuf, (int)len + 5);
+#ifdef DEBUG
+ printf("Written:%d\n", res);
+#endif
+ if (res == len + 5) {
+ res = iReadProt(1000);
+ if (res > 0) {
+ uint8_t LEN = RecvBuf[0];
+ uint16_t RCRC = RecvBuf[LEN - 1] + (RecvBuf[LEN] << 8);
+ uint16_t CCRC = _ui16CalculateCrc(RecvBuf, LEN - 1);
+#ifdef DEBUG
+ printf("CRC: %04X %04X\n", RCRC, CCRC);
+#endif
+ if (RCRC == CCRC) {
+ ProtStatus = RecvBuf[2];
+ return res;
+ } else
+ return ERR_CRC;
+ } else
+ return ERR_NOANSWER;
+
+ } else
+ return ERR_WRITE;
+ return res;
+}
+
+/**
+ * MU80X iSendProt (overloaded version)
+ *
+ * @param len number of bytes to write.
+ * @param adr address to send.
+ * @param cmd command to send.
+ * @param data data to send
+ * @param wait number of ms to wait
+ * @returns number of bytes written, or error code.
+ */
+int MU80X::iSendProt(uint8_t len, uint8_t adr, uint8_t cmd, unsigned char *data,
+ int wait) {
+ int res = 0;
+ uint16_t CRC = 0;
+ SendBuf[0] = len + 4;
+ SendBuf[1] = adr;
+ SendBuf[2] = cmd;
+ memcpy(&SendBuf[3], data, len);
+ CRC = _ui16CalculateCrc(SendBuf, len + 3);
+ SendBuf[3 + len] = CRC & 0xFF;
+ SendBuf[4 + len] = CRC >> 8;
+#ifdef DEBUG
+ printf("Send:");
+ DumpBuffer(SendBuf, len + 5);
+#endif
+ res = serial_write(_devh, (unsigned char*)SendBuf, (int)len + 5);
+#ifdef DEBUG
+ printf("SendProt wrtn:%d ", res);
+#endif
+ if (res == len + 5) {
+ res = iReadProt(wait);
+#ifdef DEBUG
+ printf(" rcvd:%d\n",res);fflush(stderr);
+#endif
+ if (res > 0) {
+ uint8_t LEN = RecvBuf[0];
+ uint16_t RCRC = RecvBuf[LEN - 1] + (RecvBuf[LEN] << 8);
+ uint16_t CCRC = _ui16CalculateCrc(RecvBuf, LEN - 1);
+ if (RCRC == CCRC) {
+ ProtStatus = RecvBuf[2];
+ return res;
+ } else
+ return ERR_CRC;
+ } else
+ return ERR_NOANSWER;
+
+ } else
+ return ERR_WRITE;
+ return res;
+}
+
+// protocol implementation
+
+/**
+ * MU80X iBufferInventory
+ *
+ * @param Q Q value.
+ * @param antenna number of antanna to use.
+ * @param time tbd.
+ * @returns number of bytes written, or error code.
+ */
+
+int MU80X::iBufferInventory(uint8_t Q, uint8_t antenna, uint8_t time) {
+ int res = 0;
+ unsigned char param[16];
+ param[0] = Q; // QV
+ param[1] = 0xFF; // SS = TID:01 EPC:FF
+ param[2] = 0x00; // TG no clue
+ param[3] = 0x80 + antenna;
+ param[4] = time;
+ res = iSendProt(5, _devid, 0x18, param, 20000);
+ if (res > 0) {
+#ifdef DEBUG
+ printf("INV:%d Stat:%d\n",res,ProtStatus);fflush(stdout);
+#endif
+// DumpBuffer(RecvBuf, res);
+ printf("-------------------------\n");
+ fflush (stdout);
+ if (RecvBuf[0] == 9) {
+ TagsInBuffer = RecvBuf[5] + (RecvBuf[4] << 8);
+ TagsSeen = RecvBuf[7] + (RecvBuf[6] << 8);
+ }
+ }
+ return res;
+
+}
+
+/**
+ * MU80X iClearBuffer
+ *
+ * @returns number of bytes cleared, or error code.
+ */
+int MU80X::iClearBuffer() {
+ int res;
+ res = iSendProt(0, _devid, 0x73, NULL);
+ return res;
+}
+
+/**
+ * MU80X iBufferInventory
+ *
+ * @param tagbuf buttfer for tags.
+ * @returns number of tags found
+ */
+int MU80X::iGetBuffer(Tag_t *tagbuf) {
+ int res = 0;
+ int havedata = 1;
+ int tagcount = 0;
+ int todecode = 0;
+ int decoded = 0;
+ int readmore = 0;
+ res = iSendProt(0, _devid, 0x72, NULL);
+ if (res < 0)
+ return res;
+ while (havedata) {
+ todecode = RecvBuf[4];
+ readmore = (RecvBuf[3] == 3); // == 3 !
+ decoded = _DecodeBuffer(todecode, tagcount, &RecvBuf[5], tagbuf);
+#ifdef DEBUG
+ DumpBuffer(RecvBuf,res);
+ printf("To decode:%d decoded:%d \n", todecode, decoded);
+ fflush(stdout);
+#endif
+ if (decoded == todecode) {
+ tagcount += decoded;
+ if (readmore) {
+ res = iReadProt(100);
+ if (res < 0)
+ return tagcount;
+ todecode = RecvBuf[4];
+ readmore = (RecvBuf[3] == 3); // == 3 !
+ } else
+ havedata = 0;
+ } else {
+ // sometingwong
+ return ERR_DECODE;
+ }
+ }
+ return tagcount;
+}
+
+/**
+ * MU80X iGetReaderInformation from address
+ *
+ * @param adr device address
+ * @returns Reader information.
+ */
+int MU80X::iGetReaderInformation(uint8_t addr) {
+ int res;
+ res = iSendProt(0, addr, 0x21, NULL);
+ return res;
+}
+
+/**
+ * MU80X iGetReaderInformation from _devid
+ *
+ * @returns Reader information.
+ */
+int MU80X::iGetReaderInformation() {
+ int res;
+ res = iSendProt(0, _devid, 0x21, NULL);
+ return res;
+}
+
+/**
+ * MU80X iGetReaderSerial from _devid
+ *
+ * @returns Reader information.
+ */
+int MU80X::iGetReaderSerial() {
+ int res;
+ res = iSendProt(0, _devid, 0x4C, NULL);
+ return res;
+}
+
+/**
+ * MU80X iSetBaud
+ *
+ * @param bd baud rate: 0=9600,1=19200,2=38400,5=57600,115200
+ * @returns 0 on success, error code otherwise.
+ */
+int MU80X::iSetBaud(uint8_t bd) { // 0=9600,1=19200,2=38400,5=57600,115200
+ int res;
+ unsigned char param[2];
+ param[0] = bd;
+ param[1] = 0;
+ res = iSendProt(1, _devid, 0x28, param);
+ return res;
+}
+
+/**
+ * MU80X iSetPower
+ *
+ * @param dbm sending power in dbm
+ * @returns 0 on success, error code otherwise.
+ */
+int MU80X::iSetPower(uint8_t dBm) {
+ int res;
+ unsigned char param[2];
+ param[0] = dBm;
+ param[1] = 0;
+ res = iSendProt(1, _devid, 0x2F, param);
+ return res;
+}
+
+/**
+ * MU80X iSetRFRegion
+ *
+ * @returns 0 on success, error code otherwise.
+ */
+int MU80X::iSetRFRegion() {
+ int res;
+ unsigned char param[2];
+ param[0] = 0x4E; // 0x01 001110 maximum band = 1 + 865,1 + (14x200KHz=2,8 MHz) = 867,9
+ param[1] = 0x00; // 0x00 000000 minimum band = 0 = 865,1 MHz + (0 x 200KHz)
+ param[2] = 0;
+ res = iSendProt(2, _devid, 0x22, param);
+ return res;
+}
+
+/**
+ * MU80X iSetScantime
+ *
+ * @param time integer in 100ms units
+ * @returns 0 on success, error code otherwise.
+ */
+int MU80X::iSetScantime(uint8_t time) { // x * 100ms
+ int res;
+ unsigned char param[2];
+ param[0] = time;
+ param[1] = 0;
+ res = iSendProt(1, _devid, 0x25, param);
+ return res;
+}
+
diff --git a/software/drivers/MU80X.h b/software/drivers/MU80X.h
new file mode 100644
index 0000000..58c006d
--- /dev/null
+++ b/software/drivers/MU80X.h
@@ -0,0 +1,111 @@
+/*
+ * MU80X.h
+ *
+ * Created on: 26.02.2022
+ * Author: steffen
+ * SPDX-FileCopyrightText: 2022 MDC Service <info@mdc-service.de>
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+
+#ifndef MU80X_H_
+#define MU80X_H_
+#include "main.h"
+
+#define ESP32
+
+#ifdef ESP32
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "esp_event.h"
+#include "esp_log.h"
+#include "driver/uart.h"
+#else
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <termios.h>
+#endif
+
+#define HashSize 16
+#define CRC_POLY_16 0x8005
+#define ProtBufLen 260
+
+#define ERR_NOERR 0
+#define ERR_CRC -1
+#define ERR_WRITE -2
+#define ERR_NOANSWER -3
+#define ERR_DECODE -4
+
+#define BAUD_9600 0
+#define BAUD_19200 1
+#define BAUD_38400 2
+#define BAUD_57600 5
+#define BAUD_115200 6
+
+class MU80X {
+public:
+#ifdef ESP32
+ MU80X(const int fh);
+#else
+ MU80X(const char *dev = "/dev/ttyUSB0", const uint16_t baud = 57600);
+#endif
+ ~MU80X(void);
+
+ int ConnectionStatus;
+ int iBufferInventory(uint8_t Q, uint8_t antenna, uint8_t time);
+ int iClearBuffer(void); // done
+ void DumpBuffer(unsigned char *buf, int len);
+ int iGetBuffer(Tag_t *tagarr);
+ int iGetReaderInformation();
+ int iGetReaderInformation(uint8_t addr);
+ int iGetReaderSerial(); // done
+ // int iGetGPI(void);
+// int iGetRFIDSettings();
+// int iReset(void);
+ int iReadProt(int ms);
+ int iSendProt(uint8_t len, uint8_t adr, uint8_t cmd, unsigned char *data); // done
+ int iSendProt(uint8_t len, uint8_t adr, uint8_t cmd, unsigned char *data, int wait); // done
+// int iSetAntennas(int antennas); // done each antenna is represented by its bit
+ int iSetBaud(uint8_t Bd); // BAUD_XXXXX definitions
+// int iSetGPO(uint8_t GPO); // later
+ int iSetPower(uint8_t dBm);
+ int iSetRFRegion(); // fixed to ETSI
+ int iSetScantime(uint8_t time);
+ void PrintTag(Tag_t tag);
+ // int iSetRFIDSettings(int Q);
+// int iStop();
+
+ unsigned char SendBuf[ProtBufLen];
+ unsigned char RecvBuf[ProtBufLen];
+ int ProtStatus;
+ int TagsInBuffer;
+ int TagsSeen;
+
+private:
+ // void vCreateTable();
+
+// uint16_t crc_tab16_init = 0xFFFF;
+// uint16_t crc_tab16[256];
+ int serial_read(int fh,unsigned char *buf);
+ int serial_write(int fh, unsigned char * buf,int len);
+ uint16_t _ui16CalculateCrc(unsigned char *data, unsigned char len);
+ int _DecodeBuffer(int tagcount, int start, unsigned char *buf, Tag_t *tagbuf);
+
+ int _devh;
+ uint8_t _devid;
+// unsigned int _baud;
+};
+
+#endif /* MU80X_H_ */