Advertisement
Guest User

Untitled

a guest
Feb 25th, 2020
114
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.85 KB | None | 0 0
  1. * \file ucglib_xmega_hal.c
  2. * \author Wim Dolman (<a href="mailto:w.e.dolman@hva.nl">w.e.dolman@hva.nl</a>)
  3. * \date 29-08-2019
  4. * \version 2.0
  5. *
  6. * \brief Xmega Hardware Abstraction Layer for ucglib from Oli Kraus
  7. *
  8. * \details This Hardware Abstraction Layer is created confirm the
  9. * <a href"https://github.com/olikraus/ucglib/wiki/hal">instructions</a> of Oli Kraus.
  10. *
  11. * This file contains a callback function <code>ucg_com_xmega_bb()</code> that handles the
  12. * communication with the Xmega using SPI or bit banging.
  13. * The Arduino/C++ implementation of ucglib contains extra printing facilities.
  14. * This file contains a bunch of functions that implements the same facilities.
  15. * So you can use <code>ucg_SetPrintPos()</code>, <code>ucg_SetPrintDir()</code>
  16. * and in stead of <code>print</code> and <code>println</code>
  17. * you can use <code>ucg_Print()</code> which prints a formatstring.
  18. *
  19. * This print facility uses a hook in the struct ucg_t. Add to the struct these
  20. * lines:
  21. * \verbatim
  22. * #ifdef __AVR_XMEGA__
  23. * void *xmega_hook; // added pointer for print hook
  24. * #endif \endverbatim
  25. * or uses the ucg.h of the HAL package in stead
  26. */
  27.  
  28. #define F_CPU 320000000UL //!< System clock is 32 MHz
  29.  
  30. #include <avr/io.h>
  31. #include <util/delay.h>
  32. #include "csrc/ucg.h"
  33. #include <stdio.h>
  34. #include <stdlib.h>
  35. #include <stdarg.h>
  36. #include "ucglib_xmega_hal.h"
  37.  
  38. #ifndef DOXYGEN_SKIP
  39. #if UCG_XMEGA_USE==UCG_XMEGA_USING_BB
  40. #define UCG_XMEGA_SCK_PORT UCG_XMEGA_BB_SCK_PORT
  41. #define UCG_XMEGA_SDA_PORT UCG_XMEGA_BB_SDA_PORT
  42. #define UCG_XMEGA_CS_PORT UCG_XMEGA_BB_CS_PORT
  43. #define UCG_XMEGA_RESET_PORT UCG_XMEGA_BB_RESET_PORT
  44. #define UCG_XMEGA_CD_PORT UCG_XMEGA_BB_CD_PORT
  45. #define UCG_XMEGA_BLK_PORT UCG_XMEGA_BB_BLK_PORT
  46.  
  47. #define UCG_XMEGA_SCK_bm (1 << UCG_XMEGA_BB_SCK_bp)
  48. #define UCG_XMEGA_SDA_bm (1 << UCG_XMEGA_BB_SDA_bp)
  49. #define UCG_XMEGA_CS_bm (1 << UCG_XMEGA_BB_CS_bp)
  50. #define UCG_XMEGA_RESET_bm (1 << UCG_XMEGA_BB_RESET_bp)
  51. #define UCG_XMEGA_CD_bm (1 << UCG_XMEGA_BB_CD_bp)
  52. #define UCG_XMEGA_BLK_bm (1 << UCG_XMEGA_BB_BLK_bp)
  53. #define UCG_XMEGA_BLK_bp UCG_XMEGA_BB_BLK_bp
  54. #else // using SPI interface
  55. #define UCG_XMEGA_SCK_PORT UCG_XMEGA_SPI_SCK_PORT
  56. #define UCG_XMEGA_SDA_PORT UCG_XMEGA_SPI_MOSI_PORT
  57. #define UCG_XMEGA_MISO_PORT UCG_XMEGA_SPI_MISO_PORT
  58. #define UCG_XMEGA_CS_PORT UCG_XMEGA_SPI_SS_PORT
  59. #define UCG_XMEGA_RESET_PORT UCG_XMEGA_SPI_RESET_PORT
  60. #define UCG_XMEGA_CD_PORT UCG_XMEGA_SPI_CD_PORT
  61. #define UCG_XMEGA_BLK_PORT UCG_XMEGA_SPI_BLK_PORT
  62.  
  63. #define UCG_XMEGA_SCK_bm (1 << UCG_XMEGA_SPI_SCK_bp)
  64. #define UCG_XMEGA_MISO_bm (1 << UCG_XMEGA_SPI_MISO_bp)
  65. #define UCG_XMEGA_SDA_bm (1 << UCG_XMEGA_SPI_MOSI_bp)
  66. #define UCG_XMEGA_CS_bm (1 << UCG_XMEGA_SPI_SS_bp)
  67. #define UCG_XMEGA_RESET_bm (1 << UCG_XMEGA_SPI_RESET_bp)
  68. #define UCG_XMEGA_CD_bm (1 << UCG_XMEGA_SPI_CD_bp)
  69. #define UCG_XMEGA_BLK_bm (1 << UCG_XMEGA_SPI_BLK_bp)
  70. #define UCG_XMEGA_BLK_bp UCG_XMEGA_SPI_BLK_bp
  71. #endif
  72. #endif
  73.  
  74. #if (UCG_XMEGA_USE==UCG_XMEGA_USING_BB)&&(UCG_XMEGA_BLK==UCG_XMEGA_BLK_EXTERN)
  75. #warning if display is connect directly to Xmega, use UCG_XMEGA_BLK_DISABLED in stead of UCG_XMEGA_BLK_EXTERN to disable the input pin
  76. #endif
  77.  
  78. /*! \brief Initialization of the communication
  79. *
  80. * \return void
  81. */
  82. static void xmega_init(void)
  83. {
  84. UCG_XMEGA_RESET_PORT.DIRSET = UCG_XMEGA_RESET_bm;
  85. UCG_XMEGA_CD_PORT.DIRSET = UCG_XMEGA_CD_bm;
  86. #if UCG_XMEGA_BLK==UCG_XMEGA_BLK_DISABLED
  87. *( (register8_t *) ( &(UCG_XMEGA_BLK_PORT.PIN0CTRL) + UCG_XMEGA_BLK_bp) ) = PORT_ISC_INPUT_DISABLE_gc;
  88. #elif UCG_XMEGA_BLK==UCG_XMEGA_BLK_CONNECT
  89. UCG_XMEGA_BLK_PORT.DIRSET = UCG_XMEGA_BLK_bm;
  90. UCG_XMEGA_BLK_PORT.OUTSET = UCG_XMEGA_BLK_bm;
  91. #endif
  92.  
  93. UCG_XMEGA_SCK_PORT.DIRSET = UCG_XMEGA_SCK_bm;
  94. UCG_XMEGA_SDA_PORT.DIRSET = UCG_XMEGA_SDA_bm;
  95. UCG_XMEGA_CS_PORT.DIRSET = UCG_XMEGA_CS_bm;
  96. UCG_XMEGA_CS_PORT.OUTSET = UCG_XMEGA_CS_bm;
  97.  
  98. #if UCG_XMEGA_USE==UCG_XMEGA_USING_SPI
  99. UCG_XMEGA_MISO_PORT.DIRCLR = UCG_XMEGA_MISO_bm;
  100. UCG_XMEGA_INTERFACE.CTRL = SPI_ENABLE_bm | // enable SPI
  101. SPI_MASTER_bm | // master mode
  102. // SPI_CLK2X_bm | // no double clock speed
  103. // SPI_DORD_bm | // MSB first
  104. SPI_MODE_0_gc | // SPI mode 0
  105. SPI_PRESCALER_DIV4_gc; // prescaling 4
  106. #endif
  107. }
  108.  
  109. /*! \brief Disable communication
  110. *
  111. * \return void
  112. */
  113. static void xmega_disable(void)
  114. {
  115. #if UCG_XMEGA_USE==UCG_XMEGA_USING_SPI
  116. UCG_XMEGA_INTERFACE.CTRL = UCG_XMEGA_INTERFACE.CTRL & ~SPI_ENABLE_bm;
  117. #endif
  118. #if UCG_XMEGA_BLK==UCG_XMEGA_BLK_CONNECT
  119. UCG_XMEGA_BLK_PORT.OUTCLR = UCG_XMEGA_BLK_bm;
  120. #endif
  121. }
  122.  
  123. /*! \brief Transfer a byte
  124. *
  125. * \return void
  126. */
  127. static void xmega_transfer(uint8_t data)
  128. {
  129. #if UCG_XMEGA_USE==UCG_XMEGA_USING_BB
  130. for (uint8_t i=0; i<8; i++) {
  131. if (data & 0x80) {
  132. UCG_XMEGA_SDA_PORT.OUTSET = UCG_XMEGA_SDA_bm;
  133. } else {
  134. UCG_XMEGA_SDA_PORT.OUTCLR = UCG_XMEGA_SDA_bm;
  135. }
  136. UCG_XMEGA_SCK_PORT.OUTSET = UCG_XMEGA_SCK_bm;
  137. UCG_XMEGA_SCK_PORT.OUTCLR = UCG_XMEGA_SCK_bm;
  138. data <<= 1;
  139. }
  140.  
  141. UCG_XMEGA_SDA_PORT.OUTSET = UCG_XMEGA_SDA_bm;
  142. #else // using SPI interface
  143. UCG_XMEGA_INTERFACE.DATA = data;
  144. while(!(UCG_XMEGA_INTERFACE.STATUS & (SPI_IF_bm)));
  145. #endif
  146. }
  147.  
  148. /////////////////////////////////////////////////
  149.  
  150. /*!
  151. * Struct for compatibility printing facilities with Arduino/C++ version of library
  152. */
  153. typedef struct {
  154. FILE *fp; //!< file pointer for printing
  155. ucg_int_t tx; //!< current x coordinate of the position
  156. ucg_int_t ty; //!< current y coordinate of the position
  157. uint8_t tdir; //!< current printing direction
  158. } ucg_print_t;
  159.  
  160. ucg_t *curr_ucg; //!< global pointer necessary for the printing facilities
  161.  
  162. /*! \brief Sets the position for next "print" command.
  163. *
  164. * \param ucg pointer to struct for the display
  165. * \param x x-coordinate of the position
  166. * \param y y-coordinate of the position
  167. *
  168. * \return void
  169. */
  170. void ucg_SetPrintPos(ucg_t *ucg, ucg_int_t x, ucg_int_t y)
  171. {
  172. ((ucg_print_t *)ucg->xmega_hook)->tx = x;
  173. ((ucg_print_t *)ucg->xmega_hook)->ty = y;
  174. }
  175.  
  176. /*! \brief Gets the current position of the 'print cursor'
  177. *
  178. * \param ucg pointer to struct for the display
  179. * \param x pointer to a variable for the x-coordinate of the current position
  180. * \param y pointer to a variable for the y-coordinate of the current position
  181. *
  182. * \return void
  183. */
  184. void ucg_GetPrintPos(ucg_t *ucg, ucg_int_t *x, ucg_int_t *y)
  185. {
  186. *x = ((ucg_print_t *)ucg->xmega_hook)->tx;
  187. *y = ((ucg_print_t *)ucg->xmega_hook)->ty;
  188. }
  189.  
  190. /*! \brief Sets the direction for next "print" command.
  191. *
  192. * \param ucg pointer to struct for the display
  193. * \param dir the direction
  194. *
  195. * \return void
  196. */
  197. void ucg_SetPrintDir(ucg_t *ucg, uint8_t dir)
  198. {
  199. ((ucg_print_t *)ucg->xmega_hook)->tdir = dir;
  200. }
  201.  
  202. /*! \brief Put a character to the display at the
  203. * current position and in the current direction.
  204. *
  205. * \param ucg pointer to struct for the display
  206. * \param dir the direction
  207. *
  208. * \return void
  209. */
  210. static int ucg_Putc(char c, FILE *stream)
  211. {
  212. ucg_int_t delta;
  213. ucg_print_t *p = (ucg_print_t *) (curr_ucg->xmega_hook);
  214.  
  215. delta = ucg_DrawGlyph(curr_ucg, p->tx, p->ty, p->tdir, c);
  216.  
  217. switch(p->tdir) {
  218. case 0: p->tx += delta; break;
  219. case 1: p->ty += delta; break;
  220. case 2: p->tx -= delta; break;
  221. default: case 3: p->ty -= delta; break;
  222. }
  223.  
  224. return 1;
  225. }
  226.  
  227. /*! \brief Put a formatted string to the display at the
  228. * current position and in the current direction.
  229. *
  230. * This replaces print and println from the Arduino implementation of ucg_lib
  231. *
  232. * The Arduino style:
  233. * \verbatim
  234. * ucg.print("text ");
  235. * ucg.print(x); // x is an int
  236. * ucg.print(" more text ");
  237. * ucg.print(y); // y is a float
  238. * ucg.println(";"); \endverbatim
  239. *
  240. * The replacement in Xmega style:
  241. *\verbatim
  242. * ucg_Print(&ucg, "text %d more text %f;\n", x, y); \endverbatim
  243. *
  244. * \param ucg pointer to struct for the display
  245. * \param fmt formatstring with escape sequences
  246. * \param ... variables that are printed
  247. *
  248. * \return void
  249. */
  250. void ucg_Print(ucg_t *ucg, char *fmt, ...)
  251. {
  252. va_list vl;
  253.  
  254. curr_ucg = ucg;
  255. va_start(vl, fmt);
  256. vfprintf( ((ucg_print_t *) (curr_ucg->xmega_hook))->fp, fmt, vl);
  257. va_end(vl);
  258. }
  259.  
  260. /*! \brief Initializes the printing facilities compatible with Arduino/C++ version of library
  261. *
  262. * \param ucg pointer to struct for the display
  263. *
  264. * \return void
  265. */
  266. void ucg_PrintInit(ucg_t *ucg)
  267. {
  268. if (ucg->xmega_hook != NULL) return;
  269.  
  270. ucg_print_t *p = (ucg_print_t *) malloc(sizeof(ucg_print_t));
  271.  
  272. if (p == NULL) return;
  273.  
  274. p->fp = fdevopen(ucg_Putc, NULL);
  275. p->tx = 0;
  276. p->ty = 0;
  277. p->tdir = 0;
  278.  
  279. ucg->xmega_hook = (void *) p;
  280.  
  281. }
  282. /////////////////////////////////////////////////
  283.  
  284. /*! \brief The callback function for communication between the Xmega and the display.
  285. *
  286. * \param ucg pointer to struct for the display
  287. * \param msg number of the message (action to be done)
  288. * \param arg depends on msg: number of arguments, number of microseconds, ...
  289. * \param data pointer to 8-bit data-array with bytes that needs to be send
  290. *
  291. * \return 16-bit value, always 1
  292. */
  293. int16_t ucg_comm_xmega(ucg_t *ucg, int16_t msg, uint16_t arg, uint8_t *data)
  294. {
  295. switch(msg)
  296. {
  297. case UCG_COM_MSG_POWER_UP:
  298. xmega_init();
  299. ucg_PrintInit(ucg);
  300. break;
  301. case UCG_COM_MSG_POWER_DOWN:
  302. xmega_disable();
  303. break;
  304. case UCG_COM_MSG_DELAY:
  305. for(uint16_t i=0; i<arg; i++) {
  306. _delay_us(1);
  307. }
  308. break;
  309. case UCG_COM_MSG_CHANGE_RESET_LINE:
  310. if (arg) {
  311. UCG_XMEGA_RESET_PORT.OUTSET = UCG_XMEGA_RESET_bm;
  312. } else {
  313. UCG_XMEGA_RESET_PORT.OUTCLR = UCG_XMEGA_RESET_bm;
  314. }
  315. break;
  316. case UCG_COM_MSG_CHANGE_CS_LINE:
  317. if (arg) {
  318. UCG_XMEGA_CS_PORT.OUTSET = UCG_XMEGA_CS_bm;
  319. } else {
  320. UCG_XMEGA_CS_PORT.OUTCLR = UCG_XMEGA_CS_bm;
  321. }
  322. break;
  323. case UCG_COM_MSG_CHANGE_CD_LINE:
  324. if (arg) {
  325. UCG_XMEGA_CD_PORT.OUTSET = UCG_XMEGA_CD_bm;
  326. } else {
  327. UCG_XMEGA_CD_PORT.OUTCLR = UCG_XMEGA_CD_bm;
  328. }
  329. break;
  330. case UCG_COM_MSG_SEND_BYTE:
  331. xmega_transfer(arg);
  332. break;
  333. case UCG_COM_MSG_REPEAT_1_BYTE:
  334. while( arg > 0 ) {
  335. xmega_transfer(data[0]);
  336. arg--;
  337. }
  338. break;
  339. case UCG_COM_MSG_REPEAT_2_BYTES:
  340. while( arg > 0 ) {
  341. xmega_transfer(data[0]);
  342. xmega_transfer(data[1]);
  343. arg--;
  344. }
  345. break;
  346. case UCG_COM_MSG_REPEAT_3_BYTES:
  347. while( arg > 0 ) {
  348. xmega_transfer(data[0]);
  349. xmega_transfer(data[1]);
  350. xmega_transfer(data[2]);
  351. arg--;
  352. }
  353. break;
  354. case UCG_COM_MSG_SEND_STR:
  355. while( arg > 0 ) {
  356. xmega_transfer(*data++);
  357. arg--;
  358. }
  359. break;
  360. }
  361.  
  362. return 1;
  363. }
  364.  
  365. /////////////////////////////////////////////////
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement