owibus.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. /*
  2. * Copyright (C) 2012 by Uwe Bonnes(bon@elektron.ikp.physik.tu-darmstadt.de)
  3. *
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. *
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * 3. Neither the name of the copyright holders nor the names of
  16. * contributors may be used to endorse or promote products derived
  17. * from this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  22. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  23. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  24. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  25. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  26. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  27. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  28. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  29. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  30. * SUCH DAMAGE.
  31. *
  32. * For additional information see http://www.ethernut.de/
  33. */
  34. /*!
  35. * \file dev/owibus.c
  36. * \brief Implementation of the One-Wire API.
  37. *
  38. * \verbatim
  39. * $Id: owibus.c 5522 2014-01-07 18:16:33Z u_bonnes $
  40. * \endverbatim
  41. */
  42. #include <stdint.h>
  43. #include <sys/timer.h>
  44. #include <dev/owibus.h>
  45. /*!
  46. * \addtogroup xgOwibus
  47. */
  48. /*@{*/
  49. /* Values from http://www.maxim-ic.com/app-notes/index.mvp/id/126 */
  50. const uint16_t owi_timervalues_250ns[OWI_MODE_NONE][OWI_CMD_NONE][OWI_PHASE_NONE] = {
  51. {
  52. {
  53. 4 * 3,
  54. 4 * (3 + 480), /* H */
  55. 4 * (3 + 480), /* H*/
  56. 4 * (3 + 480 + 70), /* H + I */
  57. 4 * (3 + 480 + 70 + 410) /* H + I + J */
  58. },
  59. {
  60. 4 * 3,
  61. 4 * (3 + 6), /* A */
  62. 4 * (3 + 60), /* C */
  63. 4 * (3 + 6 + 9), /* A + E */
  64. 4 * (3 + 6 + 9 + 55) /* A + E + F*/
  65. }
  66. },
  67. {
  68. {
  69. 10,
  70. 10 + 280,
  71. 10 + 280,
  72. 10 + 280 + 34,
  73. 10 + 280 + 34 + 160
  74. },
  75. {
  76. 10,
  77. 10 + 4,
  78. 10 + 30,
  79. 10 + 4 + 4,
  80. 10 + 4 + 4 + 28
  81. }
  82. }
  83. };
  84. /*!
  85. * \brief Search the connected One-Wire bus for devices.
  86. *
  87. * \param bus Specifies the One-Wire bus.
  88. * \param diff On entry, pointer to either OWI_SEARCH_FIRST or the
  89. * device found in the last call. On exit, pointer to
  90. * either OWI_LAST_DEVICE or the diff to use in the next
  91. * call.
  92. * \param value Pointer to the Hardware ID found.
  93. *
  94. * \return OWI_SUCCESS on success, a negative value otherwise.
  95. */
  96. int OwiRomSearch(NUTOWIBUS *bus, uint8_t *diff, uint64_t *hid)
  97. {
  98. uint_fast8_t i, j, next_diff;
  99. uint8_t b, c, command;
  100. uint8_t *id = (uint8_t *) hid;
  101. int res;
  102. res = bus->OwiTouchReset(bus);
  103. if (res) {
  104. return res;
  105. }
  106. command = OWI_SEARCH_ROM;
  107. res = bus->OwiWriteBlock(bus, &command, 8);
  108. if (res) {
  109. return res;
  110. }
  111. next_diff = OWI_LAST_DEVICE; /* unchanged on last device */
  112. i = 8 * 8; /* 8 bytes */
  113. do {
  114. j = 8; /* 8 bits */
  115. do {
  116. res |= bus->OwiReadBlock(bus, &b, 1);
  117. res |= bus->OwiReadBlock(bus, &c, 1);
  118. if (c) { /* read bit */
  119. if (b) { /* read complement bit */
  120. return OWI_DATA_ERROR; /* error: no reaction on bus */
  121. }
  122. } else {
  123. if (!b) { /* Two devices with different bits here */
  124. if (*diff > i || ((*id & 1) && *diff != i)) {
  125. b = 1; /* Choose device with '1' for now */
  126. next_diff = i; /* Choose device with '0' on next pass */
  127. }
  128. }
  129. }
  130. res |= bus->OwiWriteBlock(bus, &b, 1); /* write bit */
  131. *id >>= 1;
  132. if (b) { /* store bit as id */
  133. *id |= 0x80;
  134. }
  135. i--;
  136. } while (--j && !res);
  137. id++; /* next byte */
  138. } while (i && !res);
  139. *diff = next_diff;
  140. return res;
  141. }
  142. /*!
  143. * \brief Send a command to the connected devices.
  144. *
  145. * \param bus Specifies the One-Wire bus.
  146. * \param cmd Command to send.
  147. * \param hid Device to select or NULL for broadcast.
  148. *
  149. * \return OWI_SUCCESS on success, a negative value otherwise.
  150. */
  151. int OwiCommand(NUTOWIBUS *bus, uint8_t cmd, uint64_t *hid)
  152. {
  153. int res;
  154. uint8_t command;
  155. res = bus->OwiTouchReset(bus);
  156. if (res) {
  157. return res;
  158. }
  159. if (hid) {
  160. uint8_t *id = (uint8_t *) hid;
  161. command = OWI_MATCH_ROM;
  162. res = bus->OwiWriteBlock(bus, &command, 8); /* to a single device */
  163. res = bus->OwiWriteBlock(bus, id, 64);
  164. } else {
  165. command = OWI_SKIP_ROM; /* to all devices */
  166. res = bus->OwiWriteBlock(bus, &command, 8);
  167. }
  168. res = bus->OwiWriteBlock(bus, &cmd, 8);
  169. return 0;
  170. }
  171. /*!
  172. * \brief Read a block of data
  173. *
  174. * \param bus Specifies the One-Wire bus.
  175. * \param data Data read.
  176. * \param len Number of bits to read.
  177. *
  178. * \return OWI_SUCCESS on success, a negative value otherwise.
  179. */
  180. int OwiReadBlock(NUTOWIBUS *bus, uint8_t *data, uint_fast8_t len)
  181. {
  182. return bus->OwiReadBlock(bus, data, len);
  183. }
  184. /*!
  185. * \brief Write a block of data
  186. *
  187. * \param bus Specifies the One-Wire bus.
  188. * \param data Data to write.
  189. * \param len Number of bits to write.
  190. *
  191. * \return OWI_SUCCESS on success, a negative value otherwise.
  192. */
  193. int OwiWriteBlock(NUTOWIBUS *bus, uint8_t *data, uint_fast8_t len)
  194. {
  195. return bus->OwiWriteBlock(bus, data, len);
  196. }
  197. /*!
  198. * \brief Set/Reset One-Wire Mode(s)
  199. *
  200. * \param bus Specifies the One-Wire bus.
  201. * \param mode Bitmask of mode to set, at present only OWI_OVERDRIVE
  202. *
  203. * \return OWI_SUCCESS on success, a negative value otherwise.
  204. */
  205. int OwiSetMode(NUTOWIBUS *bus, uint_fast8_t mode)
  206. {
  207. int res;
  208. if (mode & OWI_OVERDRIVE) {
  209. uint8_t command[1] = { OWI_OVERDRIVE_SKIP_ROM };
  210. res = bus->OwiTouchReset(bus);
  211. if (res) {
  212. return res;
  213. }
  214. bus->OwiWriteBlock(bus, command, 8);
  215. bus->mode |= OWI_OVERDRIVE;
  216. res = bus->OwiTouchReset(bus);
  217. if (res) {
  218. bus->mode &= ~OWI_OVERDRIVE;
  219. return res;
  220. }
  221. } else {
  222. res = bus->OwiTouchReset(bus);
  223. }
  224. return res;
  225. }
  226. /*!
  227. * \brief Set/Reset One-Wire Mode(s)
  228. *
  229. * \param bus Specifies the One-Wire bus.
  230. *
  231. * \return Mask of set modes
  232. */
  233. int OWIGetMode(NUTOWIBUS *bus)
  234. {
  235. return bus->mode;
  236. }
  237. /*!
  238. * \brief Initialize the Owi Bus
  239. *
  240. * \param bus Specifies the One-Wire bus.
  241. *
  242. * \return OWI_SUCCESS on success, a negative value otherwise.
  243. */
  244. int OwiInit(NUTOWIBUS *bus)
  245. {
  246. if (bus->OwiSetup) {
  247. int res = bus->OwiSetup(bus);
  248. NutSleep(1);
  249. return res;
  250. }
  251. else
  252. return OWI_SUCCESS;
  253. }
  254. /*@}*/