Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: IM920_sample IM920_SDlog IM920_sample IM920_sample3 ... more
Revision 0:d3ab05ed8142, committed 2014-12-26
- Comitter:
- okini3939
- Date:
- Fri Dec 26 15:35:20 2014 +0000
- Child:
- 1:81b2fd407327
- Commit message:
- 1st tiny build.;
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/CBuffer.h Fri Dec 26 15:35:20 2014 +0000
@@ -0,0 +1,82 @@
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef CIRCBUFFER_H_
+#define CIRCBUFFER_H_
+
+template <class T>
+class CircBuffer {
+public:
+ CircBuffer(int length, void *addr = NULL) {
+ write = 0;
+ read = 0;
+ size = length + 1;
+ if (addr) {
+ buf = (T *)addr;
+ } else {
+ buf = (T *)malloc(size * sizeof(T));
+ }
+ if (buf == NULL)
+ error("Can't allocate memory");
+ };
+
+ bool isFull() {
+ return (((write + 1) % size) == read);
+ };
+
+ bool isEmpty() {
+ return (read == write);
+ };
+
+ void queue(T k) {
+ if (isFull()) {
+// read++;
+// read %= size;
+ return;
+ }
+ buf[write++] = k;
+ write %= size;
+ }
+
+ void flush() {
+ read = 0;
+ write = 0;
+ }
+
+
+ uint32_t available() {
+ return (write >= read) ? write - read : size - read + write;
+ };
+
+ bool dequeue(T * c) {
+ bool empty = isEmpty();
+ if (!empty) {
+ *c = buf[read++];
+ read %= size;
+ }
+ return(!empty);
+ };
+
+private:
+ volatile uint32_t write;
+ volatile uint32_t read;
+ uint32_t size;
+ T * buf;
+};
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/IM920.cpp Fri Dec 26 15:35:20 2014 +0000
@@ -0,0 +1,54 @@
+#include "IM920.h"
+
+IM920::IM920 (PinName tx, PinName rx, PinName busy, PinName reset, int baud) : _im(tx, rx) {
+
+ memset(&_state, 0, sizeof(_state));
+ _state.data = new CircBuffer<char>(CFG_DATA_SIZE);
+
+ initUart(busy, reset, baud);
+ setReset(true);
+ wait_ms(100);
+ setReset(false);
+}
+
+int IM920::init (int node, void(*func)()) {
+
+ _state.node = node;
+ _state.func = func;
+
+ cmdRDID();
+ cmdSTNN(_state.node);
+ cmdSTPO(3); // 10dBm
+ cmdSTRT(2); // 1.25kbps
+ return 0;
+}
+
+void IM920::poll () {
+
+ if (_state.received && _state.buf != NULL)
+ if (_state.func != NULL && !_state.data->isEmpty()) {
+ _state.func();
+ if (_state.data->isEmpty()) {
+ _state.received = false;
+ }
+ }
+}
+
+int IM920::send (char *buf, int len) {
+
+ if (len > 64) len = 64;
+
+ return sendData(buf, len);
+}
+
+int IM920::recv (char *buf, int len) {
+ int i;
+
+ if (_state.data == NULL) return 0;
+ while (!_state.received && _state.mode != MODE_COMMAND);
+ _state.received = false;
+ for (i = 0; i < len; i ++) {
+ if (_state.data->dequeue(&buf[i]) == false) break;
+ }
+ return i;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/IM920.h Fri Dec 26 15:35:20 2014 +0000
@@ -0,0 +1,126 @@
+#ifndef _IM920_h_
+#define _IM920_h_
+
+#include "IM920_conf.h"
+
+#include "mbed.h"
+#include "CBuffer.h"
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+//Debug is disabled by default
+#if defined(DEBUG) and (!defined(TARGET_LPC11U24))
+#define DBG(x, ...) std::printf("[DBG]" x "\r\n", ##__VA_ARGS__);
+#define WARN(x, ...) std::printf("[WARN]" x "\r\n", ##__VA_ARGS__);
+#define ERR(x, ...) std::printf("[ERR]" x "\r\n", ##__VA_ARGS__);
+#define INFO(x, ...) std::printf("[INFO]" x "\r\n", ##__VA_ARGS__);
+#else
+#define DBG(x, ...)
+#define WARN(x, ...)
+#define ERR(x, ...)
+#define INFO(x, ...)
+#endif
+
+class IM920 {
+public:
+ enum Response {
+ RES_NULL,
+ RES_RDID,
+ RES_RDNN,
+ RES_RDRS,
+ };
+
+ enum Mode {
+ MODE_COMMAND,
+ MODE_DATA_RX,
+ };
+
+ enum Status {
+ STAT_NONE,
+ STAT_SLEEP,
+ };
+
+ IM920 (PinName tx, PinName rx, PinName busy = NC, PinName reset = NC, int baud = IM920_BAUD);
+
+ int init (int node, void(*func)() = NULL);
+
+ void poll ();
+
+ int send (char *buf, int len);
+ int recv (char *buf, int len);
+
+ int setCh (int ch);
+ int getRssi ();
+ int sleep ();
+ int wakeup ();
+
+ // ----- GSwifi_cmd.cpp -----
+ int sendCommand(const char * cmd, Response res = RES_NULL, int timeout = DEFAULT_WAIT_RESP_TIMEOUT);
+ int sendData(const char * data, int len, int timeout = CFG_TIMEOUT);
+
+private:
+ RawSerial _im;
+ DigitalIn *_busy;
+ DigitalOut *_reset;
+ int _baud;
+
+ struct STATE {
+ int id, node, rssi;
+
+ time_t time;
+ bool initialized;
+ volatile Mode mode;
+ volatile Status status;
+ volatile bool ok, failure;
+ volatile Response res;
+ int n;
+ char buf[CFG_BUF_SIZE];
+
+ CircBuffer<char> *data;
+ volatile bool received;
+ void(*func)();
+ } _state;
+
+ // ----- GSwifi_util.cpp -----
+ int x2i (char c);
+ char i2x (int i);
+
+ // ----- GSwifi_msg.cpp -----
+ void recvData (char c);
+ int parseMessage ();
+ void msgOk (const char*);
+ void msgError (const char*);
+ void msgConnect (const char*);
+ void resRDID (const char *buf);
+ void resRDNN (const char *buf);
+ void resRDRS (const char *buf);
+
+ // ----- GSwifi_cmd.cpp -----
+ void clearFlags ();
+ int cmdENWR ();
+ int cmdDSWR ();
+ int cmdRDID ();
+ int cmdSTNN (int n);
+ int cmdRDNN ();
+ int cmdSRID (int n);
+ int cmdERID ();
+ int cmdSTCH (int n);
+ int cmdRDRS ();
+ int cmdSTPO (int n);
+ int cmdSTRT (int n);
+ int cmdSBRT (int n);
+ int cmdDSRX ();
+ int cmdENRX ();
+
+ // ----- GSwifi_hal.cpp -----
+ void setReset (bool flg);
+ void isrUart ();
+ int getUart ();
+ void putUart (char c);
+ int lockUart (int ms);
+ void unlockUart ();
+ void initUart (PinName busy, PinName reset, int baud);
+ };
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/IM920_cmd.cpp Fri Dec 26 15:35:20 2014 +0000
@@ -0,0 +1,146 @@
+#include "IM920.h"
+
+void IM920::clearFlags () {
+ _state.ok = false;
+ _state.failure = false;
+ _state.res = RES_NULL;
+ _state.n = 0;
+}
+
+int IM920::sendCommand (const char * cmd, Response res, int timeout) {
+ int i;
+ Timer t;
+
+ if (lockUart(timeout)) return -1;
+
+ clearFlags();
+ _state.res = res;
+ for (i = 0; i < strlen(cmd); i ++) {
+ putUart(cmd[i]);
+ }
+ putUart('\r');
+ putUart('\n');
+ unlockUart();
+ INFO("command: '%s'\r\n", cmd);
+
+ if (timeout) {
+ t.start();
+ for (;;) {
+ if (_state.ok && _state.res == RES_NULL) break;
+ if (_state.failure || t.read_ms() > timeout) {
+ WARN("failure or timeout\r\n");
+ _state.res = RES_NULL;
+ return -1;
+ }
+ }
+ t.stop();
+ }
+ INFO("ok\r\n");
+ _state.res = RES_NULL;
+
+ return 0;
+}
+
+int IM920::sendData(const char * data, int len, int timeout) {
+ int i;
+ Timer t;
+
+ if (lockUart(timeout)) return -1;
+
+ clearFlags();
+ putUart('T');
+ putUart('X');
+ putUart('D');
+ putUart('A');
+ putUart(' ');
+ for (i = 0; i < len; i ++) {
+ putUart(i2x((data[i]>>4) & 0x0f));
+ putUart(i2x(data[i] & 0x0f));
+ }
+ putUart('\r');
+ putUart('\n');
+ unlockUart();
+ INFO("data: TXDA %d\r\n", len);
+
+ if (timeout) {
+ t.start();
+ for (;;) {
+ if (_state.ok) break;
+ if (_state.failure || t.read_ms() > timeout) {
+ WARN("failure or timeout\r\n");
+ return -1;
+ }
+ }
+ t.stop();
+ }
+
+ return i;
+}
+
+int IM920::cmdENWR () {
+ return sendCommand("ENWR");
+}
+
+int IM920::cmdDSWR () {
+ return sendCommand("DSWR");
+}
+
+int IM920::cmdRDID () {
+ return sendCommand("RDID", RES_RDID);
+}
+
+int IM920::cmdSTNN (int n) {
+ char cmd[CFG_CMD_SIZE];
+ sprintf(cmd, "STNN %02X", n);
+ return sendCommand(cmd);
+}
+
+int IM920::cmdRDNN () {
+ return sendCommand("RDNN", RES_RDNN);
+}
+
+int IM920::cmdSRID (int n) {
+ char cmd[CFG_CMD_SIZE];
+ sprintf(cmd, "SRID %04X", n);
+ return sendCommand(cmd);
+}
+
+int IM920::cmdERID () {
+ return sendCommand("ERID");
+}
+
+int IM920::cmdSTCH (int n) {
+ char cmd[CFG_CMD_SIZE];
+ sprintf(cmd, "STCH %02d", n);
+ return sendCommand(cmd);
+}
+
+int IM920::cmdRDRS () {
+ return sendCommand("RDRS", RES_RDRS);
+}
+
+int IM920::cmdSTPO (int n) {
+ char cmd[CFG_CMD_SIZE];
+ sprintf(cmd, "STPO %d", n);
+ return sendCommand(cmd);
+}
+
+int IM920::cmdSTRT (int n) {
+ char cmd[CFG_CMD_SIZE];
+ sprintf(cmd, "STRT %d", n);
+ return sendCommand(cmd);
+}
+
+int IM920::cmdSBRT (int n) {
+ char cmd[CFG_CMD_SIZE];
+ sprintf(cmd, "SBRT %d", n);
+ return sendCommand(cmd);
+}
+
+int IM920::cmdDSRX () {
+ return sendCommand("DSRX");
+}
+
+int IM920::cmdENRX () {
+ return sendCommand("ENRX");
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/IM920_conf.h Fri Dec 26 15:35:20 2014 +0000 @@ -0,0 +1,16 @@ +#ifndef _IM920_conf_h_ +#define _IM920_conf_h_ + +#define DEBUG +#define DEBUG_DUMP + +#define IM920_BAUD 19200 + +#define CFG_BUF_SIZE 150 +#define CFG_DATA_SIZE 64 +#define CFG_CMD_SIZE 16 + +#define DEFAULT_WAIT_RESP_TIMEOUT 500 +#define CFG_TIMEOUT 5000 + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/IM920_hal.cpp Fri Dec 26 15:35:20 2014 +0000
@@ -0,0 +1,57 @@
+#include "IM920.h"
+
+void IM920::setReset (bool flg) {
+ if (_reset) {
+ if (flg) {
+ _reset->write(0);
+ } else {
+ _reset->write(1);
+ }
+ }
+}
+
+void IM920::isrUart () {
+ recvData(getUart());
+}
+
+int IM920::getUart () {
+ return _im.getc();
+}
+
+void IM920::putUart (char c) {
+ _im.putc(c);
+}
+
+int IM920::lockUart (int ms) {
+ Timer t;
+
+ if (_busy && _busy->read()) {
+ // CTS check
+ t.start();
+ while (_busy->read()) {
+ if (t.read_ms() >= ms) {
+ DBG("cts timeout\r\n");
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
+
+void IM920::unlockUart () {
+}
+
+void IM920::initUart (PinName busy, PinName reset, int baud) {
+ _baud = baud;
+ if (_baud) _im.baud(_baud);
+ _im.attach(this, &IM920::isrUart, Serial::RxIrq);
+
+ _busy = NULL;
+ _reset = NULL;
+ if (busy != NC) {
+ _busy = new DigitalIn(busy);
+ }
+ if (reset != NC) {
+ _reset = new DigitalOut(reset);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/IM920_msg.cpp Fri Dec 26 15:35:20 2014 +0000
@@ -0,0 +1,136 @@
+#include "IM920.h"
+
+void IM920::recvData (char c) {
+ static int sub, len, count;
+ static char chr;
+
+#ifdef DEBUG_DUMP
+ if (c < 0x20 || c >= 0x7f) {
+ std::printf("_%02x", c);
+ } else {
+ std::printf("_%c", c);
+ }
+#endif
+ switch (_state.mode) {
+ case MODE_COMMAND:
+ switch (c) {
+ case 0:
+ case 0x0a: // LF
+ case 0x0d: // CR
+ _state.buf[len] = 0;
+ len = 0;
+ parseMessage();
+ break;
+ case ':':
+ if (_state.buf[2] == ',' && _state.buf[7] == ',' && len == 10) {
+ sub = 0;
+ _state.mode = MODE_DATA_RX;
+ break;
+ }
+ /* FALLTHROUGH */
+ default:
+ if (len < sizeof(_state.buf) - 1) {
+ _state.buf[len] = c;
+ }
+ len ++;
+ break;
+ }
+ break;
+
+ case MODE_DATA_RX:
+ if (c == '\r' || c == '\n') {
+ DBG("recv %d/%d\r\n", count, len);
+ _state.received = true;
+ _state.mode = MODE_COMMAND;
+ len = 0;
+ break;
+ }
+ switch (sub) {
+ case 0:
+ chr = x2i(c) << 4;
+ sub ++;
+ break;
+ case 1:
+ chr |= x2i(c);
+ sub ++;
+ if (_state.data!= NULL) {
+ _state.data->queue(chr);
+ if (_state.func != NULL && _state.data->available() >= CFG_DATA_SIZE) {
+ _state.received = true;
+ WARN("buf full");
+ }
+ }
+ count ++;
+ break;
+ case 2:
+ if (c == ',') {
+ sub = 0;
+ }
+ break;
+ }
+ }
+}
+
+#define RES_TABLE_NUM 4
+int IM920::parseMessage () {
+ int i;
+ static const struct RES_TABLE {
+ const Response res;
+ void (IM920::*func)(const char*);
+ } res_table[RES_TABLE_NUM] = {
+ {RES_NULL, NULL},
+ {RES_RDID, &IM920::resRDID},
+ {RES_RDNN, &IM920::resRDNN},
+ {RES_RDRS, &IM920::resRDRS},
+ };
+
+ if (_state.res != RES_NULL) {
+ for (i = 0; i < RES_TABLE_NUM; i ++) {
+ if (res_table[i].res == _state.res) {
+ DBG("parse res %d '%s'\r\n", i, _state.buf);
+ if (res_table[i].func != NULL) {
+ (this->*(res_table[i].func))(_state.buf);
+ }
+ }
+ }
+ }
+
+ if (strncmp(_state.buf, "OK", 2) == 0) {
+ _state.ok = true;
+ if (_state.status == STAT_SLEEP) {
+ _state.status = STAT_NONE;
+ }
+ return 0;
+ } else
+ if (strncmp(_state.buf, "NG", 2) == 0) {
+ _state.failure = true;
+ return 0;
+ }
+
+ return -1;
+}
+
+void IM920::resRDID (const char *buf) {
+
+ if (buf[0] < '0' || buf[0] > 'F') return;
+
+ _state.id = strtol(buf, NULL, 16);
+ _state.res = RES_NULL;
+}
+
+void IM920::resRDNN (const char *buf) {
+
+ if (buf[0] < '0' || buf[0] > 'F') return;
+
+ _state.node = strtol(buf, NULL, 16);
+ _state.res = RES_NULL;
+}
+
+void IM920::resRDRS (const char *buf) {
+
+ if (buf[0] < '0' || buf[0] > 'F') return;
+
+ _state.rssi = strtol(buf, NULL, 16);
+ _state.res = RES_NULL;
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/IM920_util.cpp Fri Dec 26 15:35:20 2014 +0000
@@ -0,0 +1,50 @@
+#include "IM920.h"
+
+int IM920::setCh (int ch) {
+ if (ch < 1 || ch > 15) return false;
+ return cmdSTCH(ch);
+}
+
+int IM920::getRssi () {
+ cmdRDRS();
+ return _state.rssi;
+}
+
+int IM920::sleep () {
+ if (_state.status != STAT_NONE) return -1;
+
+ _state.status = STAT_SLEEP;
+ return cmdDSRX();
+}
+
+int IM920::wakeup () {
+ if (_state.status != STAT_SLEEP) return -1;
+
+ putUart('\r');
+ putUart('\n');
+ return cmdENRX();
+}
+
+
+int IM920::x2i (char c) {
+ if (c >= '0' && c <= '9') {
+ return c - '0';
+ } else
+ if (c >= 'A' && c <= 'F') {
+ return c - 'A' + 10;
+ } else
+ if (c >= 'a' && c <= 'f') {
+ return c - 'a' + 10;
+ }
+ return 0;
+}
+
+char IM920::i2x (int i) {
+ if (i >= 0 && i <= 9) {
+ return i + '0';
+ } else
+ if (i >= 10 && i <= 15) {
+ return i - 10 + 'A';
+ }
+ return 0;
+}