PageRenderTime 30ms CodeModel.GetById 33ms RepoModel.GetById 0ms app.codeStats 0ms

/avr/old/avrfbus/fbus.c

https://bitbucket.org/qartis/dori
C | 409 lines | 348 code | 54 blank | 7 comment | 83 complexity | 154f41866d81920727510e8dcab261ae MD5 | raw file
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <avr/io.h>
  4. #include <util/delay.h>
  5. #include "timer.h"
  6. #include "fbus.h"
  7. #include "power.h"
  8. #include "../uart.h"
  9. #define TYPE_SMS_MGMT 0x14
  10. #define TYPE_SMS 0x02
  11. #define TYPE_ACK 0x7f
  12. #define TYPE_GETID 0xd1
  13. #define TYPE_ID 0xd2
  14. #define TYPE_NET_STATUS 0x0a
  15. inline void print_len(const uint8_t *buf, uint8_t len){
  16. while(len--){
  17. uart_putchar(*buf++);
  18. }
  19. }
  20. uint8_t table[] = {
  21. /* ETSI GSM 03.38, version 6.0.1, section 6.2.1; Default alphabet */
  22. '@', 0xa3, '$', 0xa5, 0xe8, 0xe9, 0xf9, 0xec,
  23. 0xf2, 0xc7, '\n', 0xd8, 0xf8, '\r', 0xc5, 0xe5,
  24. '?', '_', '?', '?', '?', '?', '?', '?',
  25. '?', '?', '?', '?', 0xc6, 0xe6, 0xdf, 0xc9,
  26. ' ', '!', '\"', '#', 0xa4, '%', '&', '\'',
  27. '(', ')', '*', '+', ',', '-', '.', '/',
  28. '0', '1', '2', '3', '4', '5', '6', '7',
  29. '8', '9', ':', ';', '<', '=', '>', '?',
  30. 0xa1, 'A', 'B', 'C', 'D', 'E', 'F', 'G',
  31. 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
  32. 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
  33. 'X', 'Y', 'Z', 0xc4, 0xd6, 0xd1, 0xdc, 0xa7,
  34. 0xbf, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
  35. 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
  36. 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
  37. 'x', 'y', 'z', 0xe4, 0xf6, 0xf1, 0xfc, 0xe0
  38. };
  39. uint8_t bcd(uint8_t *dest, const char *s){
  40. uint8_t x, y, n, hi, lo;
  41. x = 0;
  42. y = 0;
  43. if (*s == '+'){
  44. s++;
  45. }
  46. while(s[x]) {
  47. lo = s[x++] - '0';
  48. if(s[x]){
  49. hi = s[x++] - '0';
  50. } else {
  51. hi = 0x0f;
  52. }
  53. n = (hi << 4) + lo;
  54. dest[y++] = n;
  55. }
  56. return y;
  57. }
  58. char* addchar(char *str, char c){
  59. *str = c;
  60. return str + 1;
  61. }
  62. char phonenum_buf[16];
  63. void unbcd_phonenum(uint8_t *data){
  64. uint8_t len, n, x, at;
  65. char *endptr = phonenum_buf;
  66. len = data[0];
  67. if(data[1] == 0x6f || data[1] == 0x91){
  68. endptr = addchar(endptr, '+');
  69. }
  70. at = 2;
  71. for(n = 0; n < len; ++n) {
  72. x = data[at] & 0x0f;
  73. if(x < 10){
  74. endptr = addchar(endptr, '0' + x);
  75. }
  76. n++;
  77. if(n >= len){
  78. break;
  79. }
  80. x = (data[at] >> 4) & 0x0f;
  81. if(x < 10){
  82. endptr = addchar(endptr, '0' + x);
  83. }
  84. at++;
  85. }
  86. *endptr = '\0';
  87. }
  88. uint8_t escaped(uint8_t c){
  89. switch (c){
  90. case 0x0a: return '\n';
  91. case 0x14: return '^';
  92. case 0x28: return '{';
  93. case 0x29: return '}';
  94. case 0x2f: return '\\';
  95. case 0x3c: return '[';
  96. case 0x3d: return '~';
  97. case 0x3e: return ']';
  98. case 0x40: return '|';
  99. default: return '?';
  100. }
  101. }
  102. char msg_buf[32];
  103. void unpack7_msg(uint8_t *data, uint8_t len){
  104. uint16_t *p, w;
  105. uint8_t c;
  106. uint8_t n;
  107. uint8_t shift = 0;
  108. uint8_t at = 0;
  109. uint8_t escape = 0;
  110. char *endptr = msg_buf;
  111. for(n = 0; n < len; ++n) {
  112. p = (uint16_t *)(data + at);
  113. w = *p;
  114. w >>= shift;
  115. c = w & 0x7f;
  116. shift += 7;
  117. if(shift & 8) {
  118. shift &= 0x07;
  119. at++;
  120. }
  121. if (escape){
  122. endptr = addchar(endptr, escaped(c));
  123. escape = 0;
  124. } else if (c == 0x1b){
  125. escape = 1;
  126. } else {
  127. endptr = addchar(endptr, table[c]);
  128. }
  129. }
  130. *endptr = '\0';
  131. }
  132. uint8_t gettrans(uint8_t c){
  133. uint8_t n;
  134. if (c == '?') return 0x3f;
  135. for (n = 0; n < 128; ++n){
  136. if (table[n] == c){
  137. return n;
  138. }
  139. }
  140. return 0x3f;
  141. }
  142. uint8_t pack7(uint8_t *dest, const char *s){
  143. uint8_t len;
  144. uint16_t *p, w;
  145. uint8_t at;
  146. uint8_t shift;
  147. uint8_t n, x;
  148. len = strlen(s);
  149. x = ((uint16_t)len * 8) / 7;
  150. for(n = 0; n < x; ++n)
  151. dest[n] = 0;
  152. shift = 0;
  153. at = 0;
  154. w = 0;
  155. for(n = 0; n < len; ++n) {
  156. p = (uint16_t *)(dest + at);
  157. w = gettrans(s[n]) & 0x7f;
  158. w <<= shift;
  159. *p |= w;
  160. shift += 7;
  161. if(shift >= 8) {
  162. shift &= 7;
  163. at++;
  164. }
  165. }
  166. return len;
  167. }
  168. void sendframe(uint8_t type, uint8_t *data, uint8_t size){
  169. static uint8_t buf[128];
  170. uint8_t at, len, n;
  171. uint16_t check;
  172. uint16_t *p;
  173. at = 0;
  174. // build header
  175. buf[at++] = 0x1e; // message startbyte
  176. buf[at++] = 0x00; // dest: phone
  177. buf[at++] = 0x0c; // source: PC
  178. buf[at++] = type;
  179. buf[at++] = 0x00;
  180. buf[at++] = size;
  181. // add data
  182. memcpy(buf+6, data, size);
  183. at += size;
  184. // if odd numbered, add filler byte
  185. if(size % 2) {
  186. buf[at++] = 0x00;
  187. }
  188. // calculate checksums
  189. check = 0;
  190. p = (uint16_t *)buf;
  191. len = at / 2;
  192. for(n = 0; n < len; ++n)
  193. check ^= p[n];
  194. p[n] = check;
  195. at += 2;
  196. // send the message!
  197. print_len(buf, at);
  198. }
  199. void sendack(uint8_t type, uint8_t seqnum){
  200. uint8_t buf[2];
  201. buf[0] = type;
  202. buf[1] = seqnum;
  203. sendframe(TYPE_ACK, buf, sizeof(buf)/sizeof(buf[0]));
  204. }
  205. enum fbus_frametype fbus_readframe(uint8_t timeout){
  206. static uint8_t buf[128];
  207. int8_t n;
  208. retry:
  209. n = read_timeout(buf, 1, timeout);
  210. if (n == -1){
  211. return FRAME_READ_TIMEOUT;
  212. }
  213. if (buf[0] != 0x1e){
  214. goto retry;
  215. }
  216. n = read_timeout(buf, 1, timeout);
  217. if (n == -1){
  218. return FRAME_READ_TIMEOUT;
  219. }
  220. if (buf[0] != 0x0c){
  221. goto retry;
  222. }
  223. n = read_timeout(buf, 1, timeout);
  224. if (n == -1){
  225. return FRAME_READ_TIMEOUT;
  226. }
  227. if (buf[0] != 0x00){
  228. goto retry;
  229. }
  230. n = read_timeout(buf, 3, timeout);
  231. if (n == -1){
  232. return FRAME_READ_TIMEOUT;
  233. }
  234. uint8_t type = buf[0];
  235. uint8_t len = buf[2];
  236. uint8_t padding = len%2;
  237. if (len > 128){
  238. return FRAME_UNKNOWN;
  239. }
  240. n = read_timeout(buf, len + padding, timeout);
  241. if (n == -1){
  242. return FRAME_READ_TIMEOUT;
  243. }
  244. uint8_t seq_no = buf[n-1-padding];
  245. uint8_t ignored_checksum[2];
  246. n = read_timeout(ignored_checksum, 2, timeout);
  247. if (n == -1){
  248. return FRAME_READ_TIMEOUT;
  249. }
  250. if (type == TYPE_ACK){
  251. goto retry;
  252. }
  253. sendack(type, seq_no & 0x0f);
  254. delay_ms(100);
  255. if (type == TYPE_SMS && buf[3] == 0x10){
  256. unbcd_phonenum(buf+23);
  257. unpack7_msg(buf+42, buf[22]);
  258. fbus_delete_sms(buf[4], buf[5]);
  259. return FRAME_SMS_RECV;
  260. } else if (type == TYPE_SMS && buf[3] == 0x02){
  261. return FRAME_SMS_SENT;
  262. } else if (type == TYPE_SMS && buf[3] == 0x03){
  263. return FRAME_SMS_ERROR;
  264. } else if (type == TYPE_ID){
  265. return FRAME_ID;
  266. } else if (type == TYPE_NET_STATUS){
  267. return FRAME_NET_STATUS;
  268. } else {
  269. return FRAME_UNKNOWN;
  270. }
  271. }
  272. void uart_sendsms(const char *num, const char *ascii){
  273. static uint8_t buf[64];
  274. uint8_t len = 0;
  275. buf[len++] = 0x00;
  276. buf[len++] = 0x01;
  277. buf[len++] = 0x00; //SMS frame header
  278. buf[len++] = 0x01;
  279. buf[len++] = 0x02;
  280. buf[len++] = 0x00; //send SMS message
  281. memset(buf+len, 0, 12);
  282. buf[len] = bcd(buf+len+2, "8613800571500") + 1; //include the type-of-address
  283. buf[len+1] = 0x91;
  284. len += 12;
  285. buf[len++] = 0x11; //SMS Submit, Reject Duplicates, Validity Indicator present
  286. buf[len++] = 0x00; //message reference
  287. buf[len++] = 0x00; //protocol id
  288. buf[len++] = 0x00; //data coding scheme
  289. buf[len++] = strlen(ascii); //data len
  290. memset(buf+len, 0, 12);
  291. buf[len] = strlen(num);
  292. buf[len+1] = 0x91;
  293. bcd(buf+len+2, num);
  294. len += 12;
  295. buf[len++] = 0xa7; //validity period, 4 days
  296. buf[len++] = 0x00;
  297. buf[len++] = 0x00;
  298. buf[len++] = 0x00;
  299. buf[len++] = 0x00;
  300. buf[len++] = 0x00;
  301. buf[len++] = 0x00;
  302. len += pack7(buf + len, ascii);
  303. buf[len++] = 0x01; //terminator
  304. buf[len++] = 0x41; //seq num
  305. if (len % 2){
  306. buf[len] = 0x00; //padding, but don't increment len
  307. }
  308. sendframe(TYPE_SMS, buf, len);
  309. }
  310. void fbus_init(void){
  311. uint8_t c;
  312. for (c = 0; c < 128; c++){
  313. uart_putchar('U');
  314. delay_ms(1);
  315. }
  316. delay_ms(1);
  317. }
  318. uint8_t fbus_sendsms(const char *num, const char *msg){
  319. enum fbus_frametype f;
  320. fbus_init();
  321. uart_sendsms(num, msg);
  322. timer_start();
  323. for(;;){
  324. f = fbus_readframe(10);
  325. if (f == FRAME_SMS_SENT){
  326. timer_disable();
  327. return 1;
  328. } else if (f == FRAME_READ_TIMEOUT){
  329. timer_disable();
  330. return 0;
  331. }
  332. //TODO what if it's an important packet?
  333. }
  334. }
  335. void fbus_delete_sms(uint8_t memory_type, uint8_t storage_loc){
  336. uint8_t del_sms[] = {0x00, 0x01, 0x00, 0x0a, memory_type, storage_loc, 0x01};
  337. fbus_init();
  338. sendframe(TYPE_SMS_MGMT, del_sms, sizeof(del_sms));
  339. }
  340. enum fbus_frametype fbus_heartbeat(void){
  341. uint8_t get_info[] = {0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x60};
  342. enum fbus_frametype type;
  343. for(;;){
  344. fbus_init();
  345. sendframe(TYPE_GETID, get_info, sizeof(get_info));
  346. timer_start();
  347. type = fbus_readframe(1);
  348. if (type != FRAME_READ_TIMEOUT){
  349. timer_disable();
  350. return type;
  351. }
  352. power_press_release();
  353. delay_ms(10000);
  354. }
  355. }