PageRenderTime 67ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/hardware/onewire/ecmd.c

https://github.com/shuairan/ethersex
C | 481 lines | 355 code | 70 blank | 56 comment | 70 complexity | 8119a5667f2bff7b87239b70ed006f36 MD5 | raw file
Possible License(s): GPL-3.0
  1. /*
  2. *
  3. * Copyright (c) by Alexander Neumann <alexander@bumpern.de>
  4. * Copyright (c) 2007 by Stefan Siegl <stesie@brokenpipe.de>
  5. * Copyright (c) 2007 by Christian Dietrich <stettberger@dokucode.de>
  6. *
  7. * This program is free software; you can redistribute it and/or modify it
  8. * under the terms of the GNU General Public License (either version 2 or
  9. * version 3) as published by the Free Software Foundation.
  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, write to the Free Software
  18. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19. *
  20. * For more information on the GPL, please go to:
  21. * http://www.gnu.org/copyleft/gpl.html
  22. */
  23. #include <string.h>
  24. #include <avr/pgmspace.h>
  25. #include <avr/eeprom.h>
  26. #include <avr/interrupt.h>
  27. #include "config.h"
  28. #include "core/debug.h"
  29. #include "core/eeprom.h"
  30. #include "core/bit-macros.h"
  31. #include "hardware/onewire/onewire.h"
  32. #include "protocols/ecmd/ecmd-base.h"
  33. /* parse an onewire rom address at cmd, write result to ptr */
  34. int8_t parse_ow_rom(char *cmd, ow_rom_code_t *rom)
  35. {
  36. uint8_t *addr = rom->bytewise;
  37. uint8_t end;
  38. #ifdef DEBUG_ECMD_OW_ROM
  39. debug_printf("called parse_ow_rom with string '%s'\n", cmd);
  40. #endif
  41. /* read 8 times 2 hex chars into a byte */
  42. int ret = sscanf_P(cmd, PSTR("%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%c"),
  43. addr+0, addr+1, addr+2, addr+3,
  44. addr+4, addr+5, addr+6, addr+7,
  45. &end);
  46. #ifdef DEBUG_ECMD_OW_ROM
  47. debug_printf("scanf returned %d\n", ret);
  48. #endif
  49. if ((ret == 8) || ((ret == 9) && (end == ' '))) {
  50. #ifdef DEBUG_ECMD_OW_ROM
  51. debug_printf("read rom %02x %02x %02x %02x %02x %02x %02x %02x\n",
  52. addr[0], addr[1], addr[2], addr[3],
  53. addr[4], addr[5], addr[6], addr[7]);
  54. #endif
  55. return 0;
  56. }
  57. return -1;
  58. }
  59. #ifdef ONEWIRE_DETECT_SUPPORT
  60. #ifdef ONEWIRE_POLLING_SUPPORT
  61. int16_t parse_cmd_onewire_list(char *cmd, char *output, uint16_t len)
  62. {
  63. int8_t list_type;
  64. while (*cmd == ' ')
  65. cmd++;
  66. switch (*cmd) {
  67. case 't':
  68. list_type = OW_LIST_TYPE_TEMP_SENSOR;
  69. break;
  70. case 'e':
  71. list_type = OW_LIST_TYPE_EEPROM;
  72. break;
  73. case '\0':
  74. list_type = OW_LIST_TYPE_ALL;
  75. break;
  76. default:
  77. return ECMD_ERR_PARSE_ERROR;
  78. }
  79. static uint8_t i=0;
  80. int16_t ret=0;
  81. do
  82. {
  83. if(ow_sensors[i].ow_rom_code.raw != 0)
  84. {
  85. if ((list_type == OW_LIST_TYPE_ALL) || (list_type == OW_LIST_TYPE_TEMP_SENSOR && ow_temp_sensor(&ow_sensors[i].ow_rom_code)) || (list_type == OW_LIST_TYPE_EEPROM && ow_eeprom(&ow_sensors[i].ow_rom_code))) {
  86. ret = snprintf_P(output, len,
  87. PSTR("%02x%02x%02x%02x%02x%02x%02x%02x"),
  88. ow_sensors[i].ow_rom_code.bytewise[0],
  89. ow_sensors[i].ow_rom_code.bytewise[1],
  90. ow_sensors[i].ow_rom_code.bytewise[2],
  91. ow_sensors[i].ow_rom_code.bytewise[3],
  92. ow_sensors[i].ow_rom_code.bytewise[4],
  93. ow_sensors[i].ow_rom_code.bytewise[5],
  94. ow_sensors[i].ow_rom_code.bytewise[6],
  95. ow_sensors[i].ow_rom_code.bytewise[7]
  96. );
  97. }
  98. }
  99. i++;
  100. }while(ret == 0 && i<OW_SENSORS_COUNT);
  101. if(i<OW_SENSORS_COUNT)
  102. return ECMD_AGAIN(ret);
  103. else
  104. {
  105. i=0;
  106. return ECMD_FINAL(ret);
  107. }
  108. }
  109. #else
  110. int16_t parse_cmd_onewire_list(char *cmd, char *output, uint16_t len)
  111. {
  112. uint8_t firstonbus = 0;
  113. int16_t ret;
  114. if (ow_global.lock == 0) {
  115. firstonbus = 1;
  116. #if ONEWIRE_BUSCOUNT > 1
  117. ow_global.bus = 0;
  118. #endif
  119. #ifdef DEBUG_ECMD_OW_LIST
  120. debug_printf("called onewire list for the first time\n");
  121. #endif
  122. #ifdef ONEWIRE_DS2502_SUPPORT
  123. /* parse optional parameters */
  124. while (*cmd == ' ')
  125. cmd++;
  126. switch (*cmd) {
  127. case 't':
  128. ow_global.list_type = OW_LIST_TYPE_TEMP_SENSOR;
  129. break;
  130. case 'e':
  131. ow_global.list_type = OW_LIST_TYPE_EEPROM;
  132. break;
  133. case '\0':
  134. ow_global.list_type = OW_LIST_TYPE_ALL;
  135. break;
  136. default:
  137. return ECMD_ERR_PARSE_ERROR;
  138. }
  139. #endif
  140. } else {
  141. #ifdef DEBUG_ECMD_OW_LIST
  142. debug_printf("called onewire list again\n");
  143. #endif
  144. firstonbus = 0;
  145. }
  146. #if defined ONEWIRE_DS2502_SUPPORT || ONEWIRE_BUSCOUNT > 1
  147. list_next: ;
  148. #endif
  149. /* disable interrupts */
  150. uint8_t sreg = SREG;
  151. cli();
  152. #if ONEWIRE_BUSCOUNT > 1
  153. ret = ow_search_rom((uint8_t)(1 << (ow_global.bus + ONEWIRE_STARTPIN)), firstonbus);
  154. #else
  155. ret = ow_search_rom(ONEWIRE_BUSMASK, firstonbus);
  156. #endif
  157. /* re-enable interrupts */
  158. SREG = sreg;
  159. /* make sure only one conversion happens at a time */
  160. ow_global.lock = 1;
  161. if (ret == 1) {
  162. #ifdef ONEWIRE_DS2502_SUPPORT
  163. if ((ow_global.list_type == OW_LIST_TYPE_ALL) ||
  164. ((ow_global.list_type == OW_LIST_TYPE_TEMP_SENSOR) &&
  165. (ow_temp_sensor(&ow_global.current_rom))) ||
  166. ((ow_global.list_type == OW_LIST_TYPE_EEPROM) &&
  167. (ow_eeprom(&ow_global.current_rom)))) {
  168. /* only print device rom address if it matches the selected list type */
  169. #endif
  170. #ifdef DEBUG_ECMD_OW_LIST
  171. debug_printf("discovered device "
  172. #if ONEWIRE_BUSCOUNT > 1
  173. "%02x %02x %02x %02x %02x %02x %02x %02x on bus %d\n",
  174. #else
  175. "%02x %02x %02x %02x %02x %02x %02x %02x\n",
  176. #endif
  177. ow_global.current_rom.bytewise[0],
  178. ow_global.current_rom.bytewise[1],
  179. ow_global.current_rom.bytewise[2],
  180. ow_global.current_rom.bytewise[3],
  181. ow_global.current_rom.bytewise[4],
  182. ow_global.current_rom.bytewise[5],
  183. ow_global.current_rom.bytewise[6],
  184. ow_global.current_rom.bytewise[7]
  185. #if ONEWIRE_BUSCOUNT > 1
  186. ,ow_global.bus);
  187. #else
  188. );
  189. #endif
  190. #endif
  191. ret = snprintf_P(output, len,
  192. PSTR("%02x%02x%02x%02x%02x%02x%02x%02x"),
  193. ow_global.current_rom.bytewise[0],
  194. ow_global.current_rom.bytewise[1],
  195. ow_global.current_rom.bytewise[2],
  196. ow_global.current_rom.bytewise[3],
  197. ow_global.current_rom.bytewise[4],
  198. ow_global.current_rom.bytewise[5],
  199. ow_global.current_rom.bytewise[6],
  200. ow_global.current_rom.bytewise[7]);
  201. #ifdef DEBUG_ECMD_OW_LIST
  202. debug_printf("generated %d bytes\n", ret);
  203. #endif
  204. /* set return value that the parser has to be called again */
  205. if (ret > 0)
  206. ret = ECMD_AGAIN(ret);
  207. #ifdef DEBUG_ECMD_OW_LIST
  208. debug_printf("returning %d\n", ret);
  209. #endif
  210. return ECMD_FINAL(ret);
  211. #ifdef ONEWIRE_DS2502_SUPPORT
  212. } else {
  213. /* device did not match list type: try again */
  214. firstonbus = 0;
  215. goto list_next;
  216. }
  217. #endif
  218. }
  219. #if ONEWIRE_BUSCOUNT > 1
  220. #ifdef DEBUG_ECMD_OW_LIST
  221. if (ret != 0) {
  222. debug_printf("no devices on bus %d\n", ow_global.bus);
  223. }
  224. #endif
  225. if (ow_global.bus < ONEWIRE_BUSCOUNT - 1) {
  226. ow_global.bus++;
  227. firstonbus = 1;
  228. goto list_next;
  229. }
  230. #endif
  231. ow_global.lock = 0;
  232. return ECMD_FINAL_OK;
  233. }
  234. #endif /* ONEWIRE_POLLING_SUPPORT*/
  235. #endif /* ONEWIRE_DETECT_SUPPORT */
  236. #ifdef ONEWIRE_POLLING_SUPPORT
  237. int16_t parse_cmd_onewire_get(char *cmd, char *output, uint16_t len)
  238. {
  239. ow_rom_code_t rom;
  240. int16_t ret;
  241. ret = parse_ow_rom(cmd, &rom);
  242. if (ret < 0)
  243. return ECMD_ERR_PARSE_ERROR;
  244. if (ow_temp_sensor(&rom)) {
  245. /*Search the sensor...*/
  246. for(uint8_t i=0;i<OW_SENSORS_COUNT;i++)
  247. {
  248. if(ow_sensors[i].ow_rom_code.raw == rom.raw)
  249. {
  250. /*Found it*/
  251. int16_t temp=ow_sensors[i].temp;
  252. div_t res = div(temp,10);
  253. ret = snprintf_P(output, len, PSTR("%d.%1d"), res.quot,res.rem);
  254. return ECMD_FINAL(ret);
  255. }
  256. }
  257. /*Sensor is not in list*/
  258. ret = snprintf_P(output, len, PSTR("Sensor not in list!"));
  259. return ECMD_FINAL(ret);
  260. #ifdef ONEWIRE_DS2502_SUPPORT
  261. } else if (ow_eeprom(&rom)) {
  262. debug_printf("reading mac\n");
  263. /* disable interrupts */
  264. uint8_t sreg = SREG;
  265. cli();
  266. uint8_t mac[6];
  267. ret = ow_eeprom_read(&rom, mac);
  268. /* re-enable interrupts */
  269. SREG = sreg;
  270. if (ret != 0) {
  271. debug_printf("mac read failed: %d\n", ret);
  272. return ECMD_ERR_READ_ERROR;
  273. }
  274. debug_printf("successfully read mac\n");
  275. debug_printf("mac: %02x:%02x:%02x:%02x:%02x:%02x\n",
  276. mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
  277. ret = snprintf_P(output, len,
  278. PSTR("mac: %02x:%02x:%02x:%02x:%02x:%02x"),
  279. mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
  280. #endif /* ONEWIRE_DS2502_SUPPORT */
  281. } else {
  282. debug_printf("unknown sensor type\n");
  283. #ifdef TEENSY_SUPPORT
  284. strcpy_P (output, PSTR("unknown sensor type"));
  285. return ECMD_FINAL(strlen(output));
  286. #else
  287. ret = snprintf_P(output, len, PSTR("unknown sensor type"));
  288. #endif
  289. }
  290. return ECMD_FINAL(ret);
  291. }
  292. #else
  293. int16_t parse_cmd_onewire_get(char *cmd, char *output, uint16_t len)
  294. {
  295. ow_rom_code_t rom;
  296. int16_t ret;
  297. while (*cmd == ' ')
  298. cmd++;
  299. debug_printf("called onewire_get with: \"%s\"\n", cmd);
  300. ret = parse_ow_rom(cmd, &rom);
  301. /* check for parse error */
  302. if (ret < 0)
  303. return ECMD_ERR_PARSE_ERROR;
  304. if (ow_temp_sensor(&rom)) {
  305. debug_printf("reading temperature\n");
  306. /* disable interrupts */
  307. uint8_t sreg = SREG;
  308. cli();
  309. ow_temp_scratchpad_t sp;
  310. ret = ow_temp_read_scratchpad(&rom, &sp);
  311. /* re-enable interrupts */
  312. SREG = sreg;
  313. if (ret != 1) {
  314. debug_printf("scratchpad read failed: %d\n", ret);
  315. return ECMD_ERR_READ_ERROR;
  316. }
  317. debug_printf("successfully read scratchpad\n");
  318. int16_t temp = ow_temp_normalize(&rom, &sp);
  319. debug_printf("temperature: %d.%d\n", HI8(temp), LO8(temp) > 0 ? 5 : 0);
  320. int8_t sign = (int8_t)(temp < 0);
  321. #ifdef TEENSY_SUPPORT
  322. if (sign) {
  323. temp = -temp;
  324. output[0] = '-';
  325. }
  326. /* Here sign is 0 or 1 */
  327. itoa (HI8(temp), output + sign, 10);
  328. char *ptr = output + strlen (output);
  329. *(ptr ++) = '.';
  330. itoa (HI8(((temp & 0x00ff) * 10) + 0x80), ptr, 10);
  331. return ECMD_FINAL(strlen(output));
  332. #else
  333. if (sign) temp = -temp;
  334. ret = snprintf_P(output, len, PSTR("%s%d.%1d"),
  335. sign?"-":"", (int8_t) HI8(temp), HI8(((temp & 0x00ff) * 10) + 0x80));
  336. #endif
  337. #ifdef ONEWIRE_DS2502_SUPPORT
  338. } else if (ow_eeprom(&rom)) {
  339. debug_printf("reading mac\n");
  340. /* disable interrupts */
  341. uint8_t sreg = SREG;
  342. cli();
  343. uint8_t mac[6];
  344. ret = ow_eeprom_read(&rom, mac);
  345. /* re-enable interrupts */
  346. SREG = sreg;
  347. if (ret != 0) {
  348. debug_printf("mac read failed: %d\n", ret);
  349. return ECMD_ERR_READ_ERROR;
  350. }
  351. debug_printf("successfully read mac\n");
  352. debug_printf("mac: %02x:%02x:%02x:%02x:%02x:%02x\n",
  353. mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
  354. ret = snprintf_P(output, len,
  355. PSTR("mac: %02x:%02x:%02x:%02x:%02x:%02x"),
  356. mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
  357. #endif /* ONEWIRE_DS2502_SUPPORT */
  358. } else {
  359. debug_printf("unknown sensor type\n");
  360. #ifdef TEENSY_SUPPORT
  361. strcpy_P (output, PSTR("unknown sensor type"));
  362. return ECMD_FINAL(strlen(output));
  363. #else
  364. ret = snprintf_P(output, len, PSTR("unknown sensor type"));
  365. #endif
  366. }
  367. return ECMD_FINAL(ret);
  368. }
  369. #endif
  370. #ifdef ONEWIRE_POLLING_SUPPORT
  371. int16_t parse_cmd_onewire_convert(char *cmd, char *output, uint16_t len)
  372. {
  373. return ECMD_FINAL_OK;
  374. }
  375. #else
  376. int16_t parse_cmd_onewire_convert(char *cmd, char *output, uint16_t len)
  377. {
  378. int16_t ret;
  379. while (*cmd == ' ')
  380. cmd++;
  381. debug_printf("called onewire_convert with: \"%s\"\n", cmd);
  382. ow_rom_code_t rom, *romptr;
  383. ret = parse_ow_rom(cmd, &rom);
  384. /* check for romcode */
  385. romptr = (ret < 0) ? NULL : &rom;
  386. debug_printf("converting temperature...\n");
  387. /* disable interrupts */
  388. uint8_t sreg = SREG;
  389. cli();
  390. ret = ow_temp_start_convert_wait(romptr);
  391. SREG = sreg;
  392. if (ret == 1)
  393. /* done */
  394. return ECMD_FINAL_OK;
  395. else if (ret == -1)
  396. /* no device attached */
  397. return ECMD_ERR_READ_ERROR;
  398. else
  399. /* wrong rom family code */
  400. return ECMD_ERR_PARSE_ERROR;
  401. }
  402. #endif
  403. /*
  404. -- Ethersex META --
  405. block([[Dallas_1-wire_Bus]])
  406. ecmd_ifdef(ONEWIRE_DETECT_SUPPORT)
  407. ecmd_feature(onewire_list, "1w list",,Return a list of the connected onewire devices)
  408. ecmd_endif()
  409. ecmd_feature(onewire_get, "1w get", DEVICE, Return temperature value of onewire DEVICE (provide 64-bit ID as 16-hex-digits))
  410. ecmd_feature(onewire_convert, "1w convert", [DEVICE], Trigger temperature conversion of either DEVICE or all connected devices)
  411. */