protocol.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. /*
  2. * This file is part of the libsigrok project.
  3. *
  4. * Copyright (C) 2013 Aurelien Jacobs <aurel@gnuage.org>
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include <string.h>
  20. #include <math.h>
  21. #include "protocol.h"
  22. typedef enum {
  23. LIVE_DATA = 0x00,
  24. LOG_METADATA = 0x11,
  25. LOG_DATA = 0x14,
  26. LOG_START = 0x18,
  27. LOG_END = 0x19,
  28. } packet_type;
  29. static gboolean appa_55ii_checksum(const uint8_t *buf)
  30. {
  31. int i, size, checksum;
  32. size = buf[3] + 4;
  33. checksum = 0;
  34. for (i = 0; i < size; i++)
  35. checksum += buf[i];
  36. return buf[size] == (checksum & 0xFF);
  37. }
  38. SR_PRIV gboolean appa_55ii_packet_valid(const uint8_t *buf)
  39. {
  40. if (buf[0] == 0x55 && buf[1] == 0x55 && buf[3] <= 32
  41. && appa_55ii_checksum(buf))
  42. return TRUE;
  43. return FALSE;
  44. }
  45. static uint64_t appa_55ii_flags(const uint8_t *buf)
  46. {
  47. uint8_t disp_mode;
  48. uint64_t flags;
  49. disp_mode = buf[4 + 13];
  50. flags = 0;
  51. if ((disp_mode & 0xF0) == 0x20)
  52. flags |= SR_MQFLAG_HOLD;
  53. if ((disp_mode & 0x0C) == 0x04)
  54. flags |= SR_MQFLAG_MAX;
  55. if ((disp_mode & 0x0C) == 0x08)
  56. flags |= SR_MQFLAG_MIN;
  57. if ((disp_mode & 0x0C) == 0x0C)
  58. flags |= SR_MQFLAG_AVG;
  59. return flags;
  60. }
  61. static float appa_55ii_temp(const uint8_t *buf, int ch)
  62. {
  63. const uint8_t *ptr;
  64. int16_t temp;
  65. uint8_t flags;
  66. ptr = buf + 4 + 14 + 3 * ch;
  67. temp = RL16(ptr);
  68. flags = ptr[2];
  69. if (flags & 0x60)
  70. return INFINITY;
  71. else if (flags & 1)
  72. return (float)temp / 10;
  73. else
  74. return (float)temp;
  75. }
  76. static void appa_55ii_live_data(struct sr_dev_inst *sdi, const uint8_t *buf)
  77. {
  78. struct dev_context *devc;
  79. struct sr_datafeed_packet packet;
  80. struct sr_datafeed_analog analog;
  81. struct sr_channel *ch;
  82. float values[APPA_55II_NUM_CHANNELS], *val_ptr;
  83. int i;
  84. devc = sdi->priv;
  85. if (devc->data_source != DATA_SOURCE_LIVE)
  86. return;
  87. val_ptr = values;
  88. memset(&analog, 0, sizeof(analog));
  89. analog.num_samples = 1;
  90. analog.mq = SR_MQ_TEMPERATURE;
  91. analog.unit = SR_UNIT_CELSIUS;
  92. analog.mqflags = appa_55ii_flags(buf);
  93. analog.data = values;
  94. for (i = 0; i < APPA_55II_NUM_CHANNELS; i++) {
  95. ch = g_slist_nth_data(sdi->channels, i);
  96. if (!ch->enabled)
  97. continue;
  98. analog.channels = g_slist_append(analog.channels, ch);
  99. *val_ptr++ = appa_55ii_temp(buf, i);
  100. }
  101. packet.type = SR_DF_ANALOG;
  102. packet.payload = &analog;
  103. sr_session_send(devc->session_cb_data, &packet);
  104. g_slist_free(analog.channels);
  105. devc->num_samples++;
  106. }
  107. static void appa_55ii_log_metadata(struct sr_dev_inst *sdi, const uint8_t *buf)
  108. {
  109. struct dev_context *devc;
  110. devc = sdi->priv;
  111. devc->num_log_records = (buf[5] << 8) + buf[4];
  112. }
  113. static void appa_55ii_log_data_parse(struct sr_dev_inst *sdi)
  114. {
  115. struct dev_context *devc;
  116. struct sr_datafeed_packet packet;
  117. struct sr_datafeed_analog analog;
  118. struct sr_channel *ch;
  119. float values[APPA_55II_NUM_CHANNELS], *val_ptr;
  120. const uint8_t *buf;
  121. int16_t temp;
  122. int offset, i;
  123. devc = sdi->priv;
  124. offset = 0;
  125. while (devc->log_buf_len >= 20 && devc->num_log_records > 0) {
  126. buf = devc->log_buf + offset;
  127. val_ptr = values;
  128. /* FIXME: Timestamp should be sent in the packet. */
  129. sr_dbg("Timestamp: %02d:%02d:%02d", buf[2], buf[3], buf[4]);
  130. memset(&analog, 0, sizeof(analog));
  131. analog.num_samples = 1;
  132. analog.mq = SR_MQ_TEMPERATURE;
  133. analog.unit = SR_UNIT_CELSIUS;
  134. analog.data = values;
  135. for (i = 0; i < APPA_55II_NUM_CHANNELS; i++) {
  136. temp = RL16(buf + 12 + 2 * i);
  137. ch = g_slist_nth_data(sdi->channels, i);
  138. if (!ch->enabled)
  139. continue;
  140. analog.channels = g_slist_append(analog.channels, ch);
  141. *val_ptr++ = temp == 0x7FFF ? INFINITY : (float)temp / 10;
  142. }
  143. packet.type = SR_DF_ANALOG;
  144. packet.payload = &analog;
  145. sr_session_send(devc->session_cb_data, &packet);
  146. g_slist_free(analog.channels);
  147. devc->num_samples++;
  148. devc->log_buf_len -= 20;
  149. offset += 20;
  150. devc->num_log_records--;
  151. }
  152. memmove(devc->log_buf, devc->log_buf + offset, devc->log_buf_len);
  153. }
  154. static void appa_55ii_log_data(struct sr_dev_inst *sdi, const uint8_t *buf)
  155. {
  156. struct dev_context *devc;
  157. const uint8_t *ptr;
  158. unsigned int size;
  159. int s;
  160. devc = sdi->priv;
  161. if (devc->data_source != DATA_SOURCE_MEMORY)
  162. return;
  163. ptr = buf + 4;
  164. size = buf[3];
  165. while (size > 0) {
  166. s = MIN(size, sizeof(devc->log_buf) - devc->log_buf_len);
  167. memcpy(devc->log_buf + devc->log_buf_len, ptr, s);
  168. devc->log_buf_len += s;
  169. size -= s;
  170. ptr += s;
  171. appa_55ii_log_data_parse(sdi);
  172. }
  173. }
  174. static void appa_55ii_log_end(struct sr_dev_inst *sdi)
  175. {
  176. struct dev_context *devc;
  177. devc = sdi->priv;
  178. if (devc->data_source != DATA_SOURCE_MEMORY)
  179. return;
  180. sdi->driver->dev_acquisition_stop(sdi, devc->session_cb_data);
  181. }
  182. static const uint8_t *appa_55ii_parse_data(struct sr_dev_inst *sdi,
  183. const uint8_t *buf, int len)
  184. {
  185. if (len < 5)
  186. /* Need more data. */
  187. return NULL;
  188. if (buf[0] != 0x55 || buf[1] != 0x55)
  189. /* Try to re-synchronize on a packet start. */
  190. return buf + 1;
  191. if (len < 5 + buf[3])
  192. /* Need more data. */
  193. return NULL;
  194. if (!appa_55ii_checksum(buf))
  195. /* Skip broken packet. */
  196. return buf + 4 + buf[3] + 1;
  197. switch ((packet_type)buf[2]) {
  198. case LIVE_DATA:
  199. appa_55ii_live_data(sdi, buf);
  200. break;
  201. case LOG_METADATA:
  202. appa_55ii_log_metadata(sdi, buf);
  203. break;
  204. case LOG_DATA:
  205. appa_55ii_log_data(sdi, buf);
  206. break;
  207. case LOG_START:
  208. break;
  209. case LOG_END:
  210. appa_55ii_log_end(sdi);
  211. break;
  212. default:
  213. sr_warn("Invalid packet type: 0x%02x.", buf[2]);
  214. break;
  215. }
  216. return buf + 4 + buf[3] + 1;
  217. }
  218. SR_PRIV int appa_55ii_receive_data(int fd, int revents, void *cb_data)
  219. {
  220. struct sr_dev_inst *sdi;
  221. struct dev_context *devc;
  222. struct sr_serial_dev_inst *serial;
  223. int64_t time;
  224. const uint8_t *ptr, *next_ptr, *end_ptr;
  225. int len;
  226. (void)fd;
  227. if (!(sdi = cb_data) || !(devc = sdi->priv) || revents != G_IO_IN)
  228. return TRUE;
  229. serial = sdi->conn;
  230. /* Try to get as much data as the buffer can hold. */
  231. len = sizeof(devc->buf) - devc->buf_len;
  232. len = serial_read(serial, devc->buf + devc->buf_len, len);
  233. if (len < 1) {
  234. sr_err("Serial port read error: %d.", len);
  235. return FALSE;
  236. }
  237. devc->buf_len += len;
  238. /* Now look for packets in that data. */
  239. ptr = devc->buf;
  240. end_ptr = ptr + devc->buf_len;
  241. while ((next_ptr = appa_55ii_parse_data(sdi, ptr, end_ptr - ptr)))
  242. ptr = next_ptr;
  243. /* If we have any data left, move it to the beginning of our buffer. */
  244. memmove(devc->buf, ptr, end_ptr - ptr);
  245. devc->buf_len -= ptr - devc->buf;
  246. /* If buffer is full and no valid packet was found, wipe buffer. */
  247. if (devc->buf_len >= sizeof(devc->buf)) {
  248. devc->buf_len = 0;
  249. return FALSE;
  250. }
  251. if (devc->limit_samples && devc->num_samples >= devc->limit_samples) {
  252. sr_info("Requested number of samples reached.");
  253. sdi->driver->dev_acquisition_stop(sdi, devc->session_cb_data);
  254. return TRUE;
  255. }
  256. if (devc->limit_msec) {
  257. time = (g_get_monotonic_time() - devc->start_time) / 1000;
  258. if (time > (int64_t)devc->limit_msec) {
  259. sr_info("Requested time limit reached.");
  260. sdi->driver->dev_acquisition_stop(sdi,
  261. devc->session_cb_data);
  262. return TRUE;
  263. }
  264. }
  265. return TRUE;
  266. }