one_wire_slave.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. #include "one_wire_slave.h"
  2. #include <furi.h>
  3. #include <furi_hal.h>
  4. #define ONEWIRE_TRSTL_MIN 270 /* Minimum Reset Low time */
  5. #define ONEWIRE_TRSTL_MAX 1200 /* Maximum Reset Low time */
  6. #define ONEWIRE_TPDH_TYP 20 /* Typical Presence Detect High time */
  7. #define ONEWIRE_TPDL_MIN 100 /* Minimum Presence Detect Low time */
  8. #define ONEWIRE_TPDL_MAX 480 /* Maximum Presence Detect Low time */
  9. #define ONEWIRE_TSLOT_MIN 60 /* Minimum Read/Write Slot time */
  10. #define ONEWIRE_TSLOT_MAX 135 /* Maximum Read/Write Slot time */
  11. #define ONEWIRE_TW1L_MAX 20 /* Maximum Master Write 1 time */
  12. #define ONEWIRE_TRL_TMSR_MAX 30 /* Maximum Master Read Low + Read Sample time */
  13. #define ONEWIRE_TH_TIMEOUT 15000 /* Maximum time before general timeout */
  14. typedef enum {
  15. OneWireSlaveErrorNone = 0,
  16. OneWireSlaveErrorResetInProgress,
  17. OneWireSlaveErrorPresenceConflict,
  18. OneWireSlaveErrorInvalidCommand,
  19. OneWireSlaveErrorTimeout,
  20. } OneWireSlaveError;
  21. struct OneWireSlave {
  22. const GpioPin* gpio_pin;
  23. OneWireSlaveError error;
  24. OneWireSlaveResetCallback reset_callback;
  25. OneWireSlaveCommandCallback command_callback;
  26. OneWireSlaveResultCallback result_callback;
  27. void* reset_callback_context;
  28. void* result_callback_context;
  29. void* command_callback_context;
  30. };
  31. /*********************** PRIVATE ***********************/
  32. static uint32_t
  33. onewire_slave_wait_while_gpio_is(OneWireSlave* bus, uint32_t time, const bool pin_value) {
  34. uint32_t start = DWT->CYCCNT;
  35. uint32_t time_ticks = time * furi_hal_cortex_instructions_per_microsecond();
  36. uint32_t time_captured;
  37. do { //-V1044
  38. time_captured = DWT->CYCCNT;
  39. if(furi_hal_gpio_read(bus->gpio_pin) != pin_value) {
  40. uint32_t remaining_time = time_ticks - (time_captured - start);
  41. remaining_time /= furi_hal_cortex_instructions_per_microsecond();
  42. return remaining_time;
  43. }
  44. } while((time_captured - start) < time_ticks);
  45. return 0;
  46. }
  47. static bool onewire_slave_show_presence(OneWireSlave* bus) {
  48. // wait until the bus is high (might return immediately)
  49. onewire_slave_wait_while_gpio_is(bus, ONEWIRE_TRSTL_MAX, false);
  50. // wait while master delay presence check
  51. furi_delay_us(ONEWIRE_TPDH_TYP);
  52. // show presence
  53. furi_hal_gpio_write(bus->gpio_pin, false);
  54. furi_delay_us(ONEWIRE_TPDL_MIN);
  55. furi_hal_gpio_write(bus->gpio_pin, true);
  56. // somebody also can show presence
  57. const uint32_t wait_low_time = ONEWIRE_TPDL_MAX - ONEWIRE_TPDL_MIN;
  58. // so we will wait
  59. if(onewire_slave_wait_while_gpio_is(bus, wait_low_time, false) == 0) {
  60. bus->error = OneWireSlaveErrorPresenceConflict;
  61. return false;
  62. }
  63. return true;
  64. }
  65. static inline bool onewire_slave_receive_and_process_command(OneWireSlave* bus) {
  66. /* Reset condition detected, send a presence pulse and reset protocol state */
  67. if(bus->error == OneWireSlaveErrorResetInProgress) {
  68. if(onewire_slave_show_presence(bus)) {
  69. bus->error = OneWireSlaveErrorNone;
  70. if(bus->reset_callback != NULL) {
  71. bus->reset_callback(bus->reset_callback_context);
  72. }
  73. return true;
  74. }
  75. } else if(bus->error == OneWireSlaveErrorNone) {
  76. uint8_t command;
  77. if(!onewire_slave_receive(bus, &command, 1)) {
  78. /* Upon failure, request an additional iteration to
  79. choose the appropriate action by checking bus->error */
  80. return true;
  81. } else if(bus->command_callback) {
  82. return bus->command_callback(command, bus->command_callback_context);
  83. } else {
  84. bus->error = OneWireSlaveErrorInvalidCommand;
  85. }
  86. }
  87. return false;
  88. }
  89. static inline bool onewire_slave_bus_start(OneWireSlave* bus) {
  90. FURI_CRITICAL_ENTER();
  91. furi_hal_gpio_init(bus->gpio_pin, GpioModeOutputOpenDrain, GpioPullNo, GpioSpeedLow);
  92. /* Start in Reset state in order to send a presence pulse immediately */
  93. bus->error = OneWireSlaveErrorResetInProgress;
  94. while(onewire_slave_receive_and_process_command(bus))
  95. ;
  96. const bool result = (bus->error == OneWireSlaveErrorNone);
  97. furi_hal_gpio_init(bus->gpio_pin, GpioModeInterruptRiseFall, GpioPullNo, GpioSpeedLow);
  98. FURI_CRITICAL_EXIT();
  99. return result;
  100. }
  101. static void onewire_slave_exti_callback(void* context) {
  102. OneWireSlave* bus = context;
  103. const volatile bool input_state = furi_hal_gpio_read(bus->gpio_pin);
  104. static uint32_t pulse_start = 0;
  105. if(input_state) {
  106. const uint32_t pulse_length =
  107. (DWT->CYCCNT - pulse_start) / furi_hal_cortex_instructions_per_microsecond();
  108. if((pulse_length >= ONEWIRE_TRSTL_MIN) && pulse_length <= (ONEWIRE_TRSTL_MAX)) {
  109. const bool result = onewire_slave_bus_start(bus);
  110. if(result && bus->result_callback != NULL) {
  111. bus->result_callback(bus->result_callback_context);
  112. }
  113. }
  114. } else {
  115. pulse_start = DWT->CYCCNT;
  116. }
  117. };
  118. /*********************** PUBLIC ***********************/
  119. OneWireSlave* onewire_slave_alloc(const GpioPin* gpio_pin) {
  120. OneWireSlave* bus = malloc(sizeof(OneWireSlave));
  121. bus->gpio_pin = gpio_pin;
  122. bus->error = OneWireSlaveErrorNone;
  123. return bus;
  124. }
  125. void onewire_slave_free(OneWireSlave* bus) {
  126. onewire_slave_stop(bus);
  127. free(bus);
  128. }
  129. void onewire_slave_start(OneWireSlave* bus) {
  130. furi_hal_gpio_add_int_callback(bus->gpio_pin, onewire_slave_exti_callback, bus);
  131. furi_hal_gpio_write(bus->gpio_pin, true);
  132. furi_hal_gpio_init(bus->gpio_pin, GpioModeInterruptRiseFall, GpioPullNo, GpioSpeedLow);
  133. }
  134. void onewire_slave_stop(OneWireSlave* bus) {
  135. furi_hal_gpio_write(bus->gpio_pin, true);
  136. furi_hal_gpio_init(bus->gpio_pin, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
  137. furi_hal_gpio_remove_int_callback(bus->gpio_pin);
  138. }
  139. void onewire_slave_set_reset_callback(
  140. OneWireSlave* bus,
  141. OneWireSlaveResetCallback callback,
  142. void* context) {
  143. bus->reset_callback = callback;
  144. bus->reset_callback_context = context;
  145. }
  146. void onewire_slave_set_command_callback(
  147. OneWireSlave* bus,
  148. OneWireSlaveCommandCallback callback,
  149. void* context) {
  150. bus->command_callback = callback;
  151. bus->command_callback_context = context;
  152. }
  153. void onewire_slave_set_result_callback(
  154. OneWireSlave* bus,
  155. OneWireSlaveResultCallback result_cb,
  156. void* context) {
  157. bus->result_callback = result_cb;
  158. bus->result_callback_context = context;
  159. }
  160. bool onewire_slave_receive_bit(OneWireSlave* bus) {
  161. // wait while bus is low
  162. uint32_t time = ONEWIRE_TSLOT_MAX;
  163. time = onewire_slave_wait_while_gpio_is(bus, time, false);
  164. if(time == 0) {
  165. bus->error = OneWireSlaveErrorResetInProgress;
  166. return false;
  167. }
  168. // wait while bus is high
  169. time = ONEWIRE_TH_TIMEOUT;
  170. time = onewire_slave_wait_while_gpio_is(bus, time, true);
  171. if(time == 0) {
  172. bus->error = OneWireSlaveErrorTimeout;
  173. return false;
  174. }
  175. // wait a time of zero
  176. time = ONEWIRE_TW1L_MAX;
  177. time = onewire_slave_wait_while_gpio_is(bus, time, false);
  178. return (time > 0);
  179. }
  180. bool onewire_slave_send_bit(OneWireSlave* bus, bool value) {
  181. // wait while bus is low
  182. uint32_t time = ONEWIRE_TSLOT_MAX;
  183. time = onewire_slave_wait_while_gpio_is(bus, time, false);
  184. if(time == 0) {
  185. bus->error = OneWireSlaveErrorResetInProgress;
  186. return false;
  187. }
  188. // wait while bus is high
  189. time = ONEWIRE_TH_TIMEOUT;
  190. time = onewire_slave_wait_while_gpio_is(bus, time, true);
  191. if(time == 0) {
  192. bus->error = OneWireSlaveErrorTimeout;
  193. return false;
  194. }
  195. // choose write time
  196. if(!value) {
  197. furi_hal_gpio_write(bus->gpio_pin, false);
  198. time = ONEWIRE_TRL_TMSR_MAX;
  199. } else {
  200. time = ONEWIRE_TSLOT_MIN;
  201. }
  202. // hold line for ZERO or ONE time
  203. furi_delay_us(time);
  204. furi_hal_gpio_write(bus->gpio_pin, true);
  205. return true;
  206. }
  207. bool onewire_slave_send(OneWireSlave* bus, const uint8_t* data, size_t data_size) {
  208. furi_hal_gpio_write(bus->gpio_pin, true);
  209. size_t bytes_sent = 0;
  210. // bytes loop
  211. for(; bytes_sent < data_size; ++bytes_sent) {
  212. const uint8_t data_byte = data[bytes_sent];
  213. // bit loop
  214. for(uint8_t bit_mask = 0x01; bit_mask != 0; bit_mask <<= 1) {
  215. if(!onewire_slave_send_bit(bus, bit_mask & data_byte)) {
  216. return false;
  217. }
  218. }
  219. }
  220. return true;
  221. }
  222. bool onewire_slave_receive(OneWireSlave* bus, uint8_t* data, size_t data_size) {
  223. furi_hal_gpio_write(bus->gpio_pin, true);
  224. size_t bytes_received = 0;
  225. for(; bytes_received < data_size; ++bytes_received) {
  226. uint8_t value = 0;
  227. for(uint8_t bit_mask = 0x01; bit_mask != 0; bit_mask <<= 1) {
  228. if(onewire_slave_receive_bit(bus)) {
  229. value |= bit_mask;
  230. }
  231. if(bus->error != OneWireSlaveErrorNone) {
  232. return false;
  233. }
  234. }
  235. data[bytes_received] = value;
  236. }
  237. return true;
  238. }