Microprocessor and peripheral 2 assignments for AUTH
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

368 lines
9.4 KiB

  1. /*
  2. * \file jiffies.c
  3. * \brief
  4. * A target independent jiffy functionality
  5. *
  6. * Copyright (C) 2014 Houtouridis Christos (http://www.houtouridis.net)
  7. *
  8. * This program is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU Lesser General Public License as
  10. * published by the Free Software Foundation, either version 3
  11. * of the License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU Lesser General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public License
  19. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. *
  21. */
  22. #include "jiffies.h"
  23. static jf_t _jf;
  24. #define JF_MAX_TIM_VALUE (0xFFFF) // 16bit counters
  25. /*
  26. * ====================== Public functions ======================
  27. */
  28. /*
  29. * Link and Glue functions
  30. */
  31. /*!
  32. * \brief
  33. * Connect the Driver's Set frequency function to jiffy struct
  34. * \note
  35. * This function get a freq value and returns the timers max jiffy value
  36. * (usual this refers to timer'sauto reload value).
  37. */
  38. void jf_link_setfreq (jf_setfreq_pt pfun) {
  39. _jf.setfreq = (pfun != 0) ? pfun : 0;
  40. }
  41. /*!
  42. * \brief
  43. * Connect the timer's value to jiffy struct
  44. */
  45. void jf_link_value (jiffy_t* v) {
  46. _jf.value = (v != 0) ? v : 0;
  47. }
  48. /*
  49. * User Functions
  50. */
  51. /*!
  52. * \brief
  53. * Check jiffy's status
  54. * \return status
  55. */
  56. inline drv_status_en jf_probe (void) {
  57. return _jf.status;
  58. }
  59. /*!
  60. * \brief
  61. * De-Initialize the jf data and un-connect the functions
  62. * from the driver
  63. */
  64. void jf_deinit (void)
  65. {
  66. if (_jf.setfreq) _jf.setfreq (0, 0);
  67. memset ((void*)&_jf, 0, sizeof (jf_t));
  68. _jf.status = DRV_NODEV;
  69. }
  70. /*!
  71. * \brief
  72. * Initialize the jf to a desired jiffy frequency
  73. * \note
  74. * This function has no effect if the inner jiffy struct
  75. * is un-connected to driver. So you have to call
  76. * \sa jf_connect_setfreq() and \sa jf_connect_value() first.
  77. * \return The status of the operation
  78. * \arg DRV_ERROR If the init process fail
  79. * \arg DRV_NODEV If there is no linked jiffy HW, no setfreq function
  80. * \arg DRV_READY Success
  81. */
  82. drv_status_en jf_init (uint32_t jf_freq, jiffy_t jiffies)
  83. {
  84. if (_jf.setfreq) {
  85. _jf.status = DRV_NOINIT;
  86. if ( _jf.setfreq (jf_freq, jiffies) )
  87. return DRV_ERROR;
  88. _jf.jiffies = jiffies;
  89. _jf.freq = jf_freq;
  90. _jf.jp1ms = jf_per_msec ();
  91. _jf.jp1us = jf_per_usec ();
  92. _jf.jp100ns = jf_per_100nsec ();
  93. return _jf.status = DRV_READY;
  94. }
  95. return _jf.status = DRV_NODEV;
  96. }
  97. /*!
  98. * \brief
  99. * Return the maximum jiffy value.
  100. */
  101. jiffy_t jf_get_jiffies (void){
  102. return _jf.jiffies;
  103. }
  104. /*!
  105. * \brief
  106. * Return the current jiffy value.
  107. * \note
  108. * Usual this function returns the value of a register from a timer peripheral
  109. * in the MCU. Keep in mind that its value is a moving target!
  110. */
  111. jiffy_t jf_get_jiffy (void){
  112. return *_jf.value;
  113. }
  114. /*!
  115. * \brief
  116. * Return the systems best approximation for jiffies per msec
  117. * \return
  118. * The calculated value or zero if no calculation can apply
  119. *
  120. * \note
  121. * The result tend to differ as the jiffies and freq values decreasing
  122. */
  123. jiffy_t jf_per_msec (void)
  124. {
  125. jiffy_t jf = (jiffy_t)(_jf.freq / 1000);
  126. /* 1
  127. * 1000Hz = ----- , Its not a magic number
  128. * 1msec
  129. */
  130. if (jf <= 1) return 1;
  131. else return jf;
  132. }
  133. /*!
  134. * \brief
  135. * Return the systems best approximation for jiffies per usec
  136. * \return
  137. * The calculated value or zero if no calculation can apply
  138. *
  139. * \note
  140. * The result tend to differ as the jiffies and freq values decreasing
  141. */
  142. jiffy_t jf_per_usec (void)
  143. {
  144. jiffy_t jf = (jiffy_t)(_jf.freq / 1000000);
  145. /* 1
  146. * 1000000Hz = ------ , Its not a magic number
  147. * 1usec
  148. */
  149. if (jf <= 1) return 1;
  150. else return jf;
  151. }
  152. /*!
  153. * \brief
  154. * Return the systems best approximation for jiffies per usec
  155. * \return
  156. * The calculated value or zero if no calculation can apply
  157. *
  158. * \note
  159. * The result tend to differ as the jiffies and freq values decreasing
  160. */
  161. jiffy_t jf_per_100nsec (void)
  162. {
  163. jiffy_t jf = (jiffy_t)(_jf.freq / 10000000);
  164. /* 1
  165. * 10000000Hz = ------- , Its not a magic number
  166. * 100nsec
  167. */
  168. if (jf <= 1) return 1;
  169. else return jf;
  170. }
  171. /*!
  172. * \brief
  173. * A code based delay implementation, using jiffies for timing.
  174. * This is NOT accurate but it ensures that the time passed is always
  175. * more than the requested value.
  176. * The delay values are multiplications of 1 msec.
  177. * \param msec Time in msec for delay
  178. */
  179. void jf_delay_ms (jtime_t msec)
  180. {
  181. jtime_t m, m2, m1 = (jtime_t)*_jf.value;
  182. msec *= _jf.jp1ms;
  183. // Eat the time difference from msec value.
  184. do {
  185. m2 = (jtime_t)(*_jf.value);
  186. m = m2 - m1;
  187. msec -= (m>=0) ? m : _jf.jiffies + m;
  188. m1 = m2;
  189. } while (msec>0);
  190. }
  191. /*!
  192. * \brief
  193. * A code based delay implementation, using jiffies for timing.
  194. * This is NOT accurate but it ensures that the time passed is always
  195. * more than the requested value.
  196. * The delay values are multiplications of 1 usec.
  197. * \param usec Time in usec for delay
  198. */
  199. void jf_delay_us (jtime_t usec)
  200. {
  201. jtime_t m, m2, m1 = (jtime_t)*_jf.value;
  202. usec *= _jf.jp1us;
  203. if ((jtime_t)(*_jf.value) - m1 > usec) // Very small delays may return here.
  204. return;
  205. // Eat the time difference from usec value.
  206. do {
  207. m2 = (jtime_t)(*_jf.value);
  208. m = m2 - m1;
  209. usec -= (m>=0) ? m : _jf.jiffies + m;
  210. m1 = m2;
  211. } while (usec>0);
  212. }
  213. /*!
  214. * \brief
  215. * A code based delay implementation, using jiffies for timing.
  216. * This is NOT accurate but it ensures that the time passed is always
  217. * more than the requested value.
  218. * The delay values are multiplications of 100 nsec.
  219. * \param _100nsec Time in 100nsec for delay
  220. */
  221. void jf_delay_100ns (jtime_t _100nsec)
  222. {
  223. jtime_t m, m2, m1 = (jtime_t)*_jf.value;
  224. _100nsec *= _jf.jp100ns;
  225. if ((jtime_t)(*_jf.value) - m1 > _100nsec) // Very small delays may return here.
  226. return;
  227. // Eat the time difference from _100nsec value.
  228. do {
  229. m2 = (jtime_t)(*_jf.value);
  230. m = m2 - m1;
  231. _100nsec -= (m>=0) ? m : _jf.jiffies + m;
  232. m1 = m2;
  233. } while (_100nsec>0);
  234. }
  235. /*!
  236. * \brief
  237. * A code based polling version delay implementation, using jiffies for timing.
  238. * This is NOT accurate but it ensures that the time passed is always
  239. * more than the requested value.
  240. * The delay values are multiplications of 1 msec.
  241. * \param msec Time in msec for delay
  242. * \return The status of ongoing delay
  243. * \arg 0: Delay time has passed
  244. * \arg 1: Delay is ongoing, keep calling
  245. */
  246. int jf_check_msec (jtime_t msec)
  247. {
  248. static jtime_t m1=-1, cnt;
  249. jtime_t m, m2;
  250. if (m1 == -1) {
  251. m1 = *_jf.value;
  252. cnt = _jf.jp1ms * msec;
  253. }
  254. // Eat the time difference from msec value.
  255. if (cnt>0) {
  256. m2 = (jtime_t)(*_jf.value);
  257. m = m2-m1;
  258. cnt -= (m>=0) ? m : _jf.jiffies + m;
  259. m1 = m2;
  260. return 1; // wait
  261. }
  262. else {
  263. m1 = -1;
  264. return 0; // do not wait any more
  265. }
  266. }
  267. /*!
  268. * \brief
  269. * A code based polling version delay implementation, using jiffies for timing.
  270. * This is NOT accurate but it ensures that the time passed is always
  271. * more than the requested value.
  272. * The delay values are multiplications of 1 usec.
  273. * \param usec Time in usec for delay
  274. * \return The status of ongoing delay
  275. * \arg 0: Delay time has passed
  276. * \arg 1: Delay is ongoing, keep calling
  277. */
  278. int jf_check_usec (jtime_t usec)
  279. {
  280. static jtime_t m1=-1, cnt;
  281. jtime_t m, m2;
  282. if (m1 == -1) {
  283. m1 = *_jf.value;
  284. cnt = _jf.jp1us * usec;
  285. }
  286. // Eat the time difference from usec value.
  287. if (cnt>0) {
  288. m2 = (jtime_t)(*_jf.value);
  289. m = m2-m1;
  290. cnt -= (m>=0) ? m : _jf.jiffies + m;
  291. m1 = m2;
  292. return 1; // wait
  293. }
  294. else {
  295. m1 = -1;
  296. return 0; // do not wait any more
  297. }
  298. }
  299. /*!
  300. * \brief
  301. * A code based polling version delay implementation, using jiffies for timing.
  302. * This is NOT accurate but it ensures that the time passed is always
  303. * more than the requested value.
  304. * The delay values are multiplications of 100 nsec.
  305. * \param
  306. * _100nsec Time in 100nsec for delay
  307. * \return The status of ongoing delay
  308. * \arg 0: Delay time has passed
  309. * \arg 1: Delay is ongoing, keep calling
  310. */
  311. int jf_check_100nsec (jtime_t _100nsec)
  312. {
  313. static jtime_t m1=-1, cnt;
  314. jtime_t m, m2;
  315. if (m1 == -1) {
  316. m1 = *_jf.value;
  317. cnt = _jf.jp100ns * _100nsec;
  318. }
  319. // Eat the time difference from _100nsec value.
  320. if (cnt>0) {
  321. m2 = (jtime_t)(*_jf.value);
  322. m = m2-m1;
  323. cnt -= (m>=0) ? m : _jf.jiffies + m;
  324. m1 = m2;
  325. return 1; // wait
  326. }
  327. else {
  328. m1 = -1;
  329. return 0; // do not wait any more
  330. }
  331. }