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.
 
 
 
 
 
 

356 lines
8.7 KiB

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