usart_driver.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. /* This file has been prepared for Doxygen automatic documentation generation.*/
  2. /*! \file *********************************************************************
  3. *
  4. * \brief
  5. * XMEGA USART driver source file.
  6. *
  7. * This file contains the function implementations the XMEGA interrupt
  8. * and polled USART driver.
  9. *
  10. * The driver is not intended for size and/or speed critical code, since
  11. * most functions are just a few lines of code, and the function call
  12. * overhead would decrease code performance. The driver is intended for
  13. * rapid prototyping and documentation purposes for getting started with
  14. * the XMEGA ADC module.
  15. *
  16. * For size and/or speed critical code, it is recommended to copy the
  17. * function contents directly into your application instead of making
  18. * a function call.
  19. *
  20. * Some functions use the following construct:
  21. * "some_register = ... | (some_parameter ? SOME_BIT_bm : 0) | ..."
  22. * Although the use of the ternary operator ( if ? then : else ) is discouraged,
  23. * in some occasions the operator makes it possible to write pretty clean and
  24. * neat code. In this driver, the construct is used to set or not set a
  25. * configuration bit based on a boolean input parameter, such as
  26. * the "some_parameter" in the example above.
  27. *
  28. * \par Application note:
  29. * AVR1307: Using the XMEGA USART
  30. *
  31. * \par Documentation
  32. * For comprehensive code documentation, supported compilers, compiler
  33. * settings and supported devices see readme.html
  34. *
  35. * \author
  36. * Atmel Corporation: http://www.atmel.com \n
  37. * Support email: avr@atmel.com
  38. *
  39. * $Revision: 1694 $
  40. * $Date: 2008-07-29 14:21:58 +0200 (ti, 29 jul 2008) $ \n
  41. *
  42. * Copyright (c) 2008, Atmel Corporation All rights reserved.
  43. *
  44. * Redistribution and use in source and binary forms, with or without
  45. * modification, are permitted provided that the following conditions are met:
  46. *
  47. * 1. Redistributions of source code must retain the above copyright notice,
  48. * this list of conditions and the following disclaimer.
  49. *
  50. * 2. Redistributions in binary form must reproduce the above copyright notice,
  51. * this list of conditions and the following disclaimer in the documentation
  52. * and/or other materials provided with the distribution.
  53. *
  54. * 3. The name of ATMEL may not be used to endorse or promote products derived
  55. * from this software without specific prior written permission.
  56. *
  57. * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
  58. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  59. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND
  60. * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
  61. * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  62. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  63. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  64. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  65. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  66. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  67. *****************************************************************************/
  68. #include "usart_driver.h"
  69. /*! \brief Initializes buffer and selects what USART module to use.
  70. *
  71. * Initializes receive and transmit buffer and selects what USART module to use,
  72. * and stores the data register empty interrupt level.
  73. *
  74. * \param usart_data The USART_data_t struct instance.
  75. * \param usart The USART module.
  76. * \param dreIntLevel Data register empty interrupt level.
  77. */
  78. void USART_InterruptDriver_Initialize(USART_data_t * usart_data,
  79. USART_t * usart,
  80. USART_DREINTLVL_t dreIntLevel)
  81. {
  82. usart_data->usart = usart;
  83. usart_data->dreIntLevel = dreIntLevel;
  84. usart_data->buffer.RX_Tail = 0;
  85. usart_data->buffer.RX_Head = 0;
  86. usart_data->buffer.TX_Tail = 0;
  87. usart_data->buffer.TX_Head = 0;
  88. }
  89. /*! \brief Set USART DRE interrupt level.
  90. *
  91. * Set the interrupt level on Data Register interrupt.
  92. *
  93. * \note Changing the DRE interrupt level in the interrupt driver while it is
  94. * running will not change the DRE interrupt level in the USART before the
  95. * DRE interrupt have been disabled and enabled again.
  96. *
  97. * \param usart_data The USART_data_t struct instance
  98. * \param dreIntLevel Interrupt level of the DRE interrupt.
  99. */
  100. void USART_InterruptDriver_DreInterruptLevel_Set(USART_data_t * usart_data,
  101. USART_DREINTLVL_t dreIntLevel)
  102. {
  103. usart_data->dreIntLevel = dreIntLevel;
  104. }
  105. /*! \brief Test if there is data in the transmitter software buffer.
  106. *
  107. * This function can be used to test if there is free space in the transmitter
  108. * software buffer.
  109. *
  110. * \param usart_data The USART_data_t struct instance.
  111. *
  112. * \retval true There is data in the receive buffer.
  113. * \retval false The receive buffer is empty.
  114. */
  115. bool USART_TXBuffer_FreeSpace(USART_data_t * usart_data)
  116. {
  117. /* Make copies to make sure that volatile access is specified. */
  118. uint8_t tempHead = (usart_data->buffer.TX_Head + 1) & USART_TX_BUFFER_MASK;
  119. uint8_t tempTail = usart_data->buffer.TX_Tail;
  120. /* There are data left in the buffer unless Head and Tail are equal. */
  121. return (tempHead != tempTail);
  122. }
  123. /*! \brief Put data (5-8 bit character).
  124. *
  125. * Stores data byte in TX software buffer and enables DRE interrupt if there
  126. * is free space in the TX software buffer.
  127. *
  128. * \param usart_data The USART_data_t struct instance.
  129. * \param data The data to send.
  130. */
  131. bool USART_TXBuffer_PutByte(USART_data_t * usart_data, uint8_t data)
  132. {
  133. uint8_t tempCTRLA;
  134. uint8_t tempTX_Head;
  135. bool TXBuffer_FreeSpace;
  136. USART_Buffer_t * TXbufPtr;
  137. TXbufPtr = &usart_data->buffer;
  138. TXBuffer_FreeSpace = USART_TXBuffer_FreeSpace(usart_data);
  139. if(TXBuffer_FreeSpace)
  140. {
  141. tempTX_Head = TXbufPtr->TX_Head;
  142. TXbufPtr->TX[tempTX_Head]= data;
  143. /* Advance buffer head. */
  144. TXbufPtr->TX_Head = (tempTX_Head + 1) & USART_TX_BUFFER_MASK;
  145. /* Enable DRE interrupt. */
  146. tempCTRLA = usart_data->usart->CTRLA;
  147. tempCTRLA = (tempCTRLA & ~USART_DREINTLVL_gm) | usart_data->dreIntLevel;
  148. usart_data->usart->CTRLA = tempCTRLA;
  149. }
  150. return TXBuffer_FreeSpace;
  151. }
  152. /*! \brief Test if there is data in the receive software buffer.
  153. *
  154. * This function can be used to test if there is data in the receive software
  155. * buffer.
  156. *
  157. * \param usart_data The USART_data_t struct instance
  158. *
  159. * \retval true There is data in the receive buffer.
  160. * \retval false The receive buffer is empty.
  161. */
  162. bool USART_RXBufferData_Available(USART_data_t * usart_data)
  163. {
  164. /* Make copies to make sure that volatile access is specified. */
  165. uint8_t tempHead = usart_data->buffer.RX_Head;
  166. uint8_t tempTail = usart_data->buffer.RX_Tail;
  167. /* There are data left in the buffer unless Head and Tail are equal. */
  168. return (tempHead != tempTail);
  169. }
  170. /*! \brief Get received data (5-8 bit character).
  171. *
  172. * The function USART_RXBufferData_Available should be used before this
  173. * function is used to ensure that data is available.
  174. *
  175. * Returns data from RX software buffer.
  176. *
  177. * \param usart_data The USART_data_t struct instance.
  178. *
  179. * \return Received data.
  180. */
  181. uint8_t USART_RXBuffer_GetByte(USART_data_t * usart_data)
  182. {
  183. USART_Buffer_t * bufPtr;
  184. uint8_t ans;
  185. bufPtr = &usart_data->buffer;
  186. ans = (bufPtr->RX[bufPtr->RX_Tail]);
  187. /* Advance buffer tail. */
  188. bufPtr->RX_Tail = (bufPtr->RX_Tail + 1) & USART_RX_BUFFER_MASK;
  189. return ans;
  190. }
  191. /*! \brief RX Complete Interrupt Service Routine.
  192. *
  193. * RX Complete Interrupt Service Routine.
  194. * Stores received data in RX software buffer.
  195. *
  196. * \param usart_data The USART_data_t struct instance.
  197. */
  198. bool USART_RXComplete(USART_data_t * usart_data)
  199. {
  200. USART_Buffer_t * bufPtr;
  201. bool ans;
  202. bufPtr = &usart_data->buffer;
  203. /* Advance buffer head. */
  204. uint8_t tempRX_Head = (bufPtr->RX_Head + 1) & USART_RX_BUFFER_MASK;
  205. /* Check for overflow. */
  206. uint8_t tempRX_Tail = bufPtr->RX_Tail;
  207. uint8_t data = usart_data->usart->DATA;
  208. if (tempRX_Head == tempRX_Tail) {
  209. ans = false;
  210. }else{
  211. ans = true;
  212. usart_data->buffer.RX[usart_data->buffer.RX_Head] = data;
  213. usart_data->buffer.RX_Head = tempRX_Head;
  214. }
  215. return ans;
  216. }
  217. /*! \brief Data Register Empty Interrupt Service Routine.
  218. *
  219. * Data Register Empty Interrupt Service Routine.
  220. * Transmits one byte from TX software buffer. Disables DRE interrupt if buffer
  221. * is empty. Argument is pointer to USART (USART_data_t).
  222. *
  223. * \param usart_data The USART_data_t struct instance.
  224. */
  225. void USART_DataRegEmpty(USART_data_t * usart_data)
  226. {
  227. USART_Buffer_t * bufPtr;
  228. bufPtr = &usart_data->buffer;
  229. /* Check if all data is transmitted. */
  230. uint8_t tempTX_Tail = usart_data->buffer.TX_Tail;
  231. if (bufPtr->TX_Head == tempTX_Tail){
  232. /* Disable DRE interrupts. */
  233. uint8_t tempCTRLA = usart_data->usart->CTRLA;
  234. tempCTRLA = (tempCTRLA & ~USART_DREINTLVL_gm) | USART_DREINTLVL_OFF_gc;
  235. usart_data->usart->CTRLA = tempCTRLA;
  236. }else{
  237. /* Start transmitting. */
  238. uint8_t data = bufPtr->TX[usart_data->buffer.TX_Tail];
  239. usart_data->usart->DATA = data;
  240. /* Advance buffer tail. */
  241. bufPtr->TX_Tail = (bufPtr->TX_Tail + 1) & USART_TX_BUFFER_MASK;
  242. }
  243. }
  244. /*! \brief Put data (9 bit character).
  245. *
  246. * Use the function USART_IsTXDataRegisterEmpty before using this function to
  247. * put 9 bit character to the TX register.
  248. *
  249. * \param usart The USART module.
  250. * \param data The data to send.
  251. */
  252. void USART_NineBits_PutChar(USART_t * usart, uint16_t data)
  253. {
  254. if(data & 0x0100) {
  255. usart->CTRLB |= USART_TXB8_bm;
  256. }else {
  257. usart->CTRLB &= ~USART_TXB8_bm;
  258. }
  259. usart->DATA = (data & 0x00FF);
  260. }
  261. /*! \brief Get received data (9 bit character).
  262. *
  263. * This function reads out the received 9 bit character (uint16_t).
  264. * Use the function USART_IsRXComplete to check if anything is received.
  265. *
  266. * \param usart The USART module.
  267. *
  268. * \retval Received data.
  269. */
  270. uint16_t USART_NineBits_GetChar(USART_t * usart)
  271. {
  272. if(usart->CTRLB & USART_RXB8_bm) {
  273. return(0x0100 | usart->DATA);
  274. }else {
  275. return(usart->DATA);
  276. }
  277. }