nrf6350.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. /**
  2. * Copyright (c) 2008 - 2020, Nordic Semiconductor ASA
  3. *
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without modification,
  7. * are permitted provided that the following conditions are met:
  8. *
  9. * 1. Redistributions of source code must retain the above copyright notice, this
  10. * list of conditions and the following disclaimer.
  11. *
  12. * 2. Redistributions in binary form, except as embedded into a Nordic
  13. * Semiconductor ASA integrated circuit in a product or a software update for
  14. * such product, must reproduce the above copyright notice, this list of
  15. * conditions and the following disclaimer in the documentation and/or other
  16. * materials provided with the distribution.
  17. *
  18. * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
  19. * contributors may be used to endorse or promote products derived from this
  20. * software without specific prior written permission.
  21. *
  22. * 4. This software, with or without modification, must only be used with a
  23. * Nordic Semiconductor ASA integrated circuit.
  24. *
  25. * 5. Any software provided in binary form under this license must not be reverse
  26. * engineered, decompiled, modified and/or disassembled.
  27. *
  28. * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
  29. * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  30. * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
  31. * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
  32. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  33. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  34. * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  35. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  36. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  37. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  38. *
  39. */
  40. #include "nrf6350.h"
  41. #include "nrf_delay.h"
  42. #include "twi_master.h"
  43. /*lint ++flb "Enter library region" */
  44. #define DDRAM_ADR 0x80 //!< Write to DDRAM AC
  45. #define DDRAM_WR 0x40 //!< Write to DDRAM
  46. #define FUNC_SET 0x00 //!< Enter LCD Function settings
  47. #define LCD_ADDR 0x3E //!< LCD display adr
  48. #define JS_ADDR 0x3F //!< Joystick adr
  49. #define X 0 //!< X direction in pos 0 of joystick array
  50. #define Y 1 //!< Y direction in pos 1 of joystick array
  51. //static void nrf6350_nrf6350_lcd_set_instruction(uint8_t instr);
  52. #define BUF_LEN 32 //!< LCD data buffer length
  53. static uint8_t data_buffer[BUF_LEN]; //!< LCD data buffer
  54. static uint8_t empty_str[18] = {DDRAM_WR, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '}; //!< Blank line
  55. static bool nrf6350_lcd_set_instruction(uint8_t instr)
  56. {
  57. nrf_delay_us(10000);
  58. data_buffer[0] = FUNC_SET;
  59. data_buffer[1] = instr;
  60. return twi_master_transfer(LCD_ADDR << 1, data_buffer, 2, TWI_ISSUE_STOP);
  61. }
  62. bool nrf6350_lcd_clear(void)
  63. {
  64. nrf_delay_us(10000);
  65. data_buffer[0] = FUNC_SET;
  66. data_buffer[1] = (uint8_t)(DDRAM_ADR + LCD_UPPER_LINE);
  67. if (!twi_master_transfer(LCD_ADDR << 1, data_buffer, 2, TWI_ISSUE_STOP))
  68. return false;
  69. if (!twi_master_transfer(LCD_ADDR << 1, empty_str, 18, TWI_ISSUE_STOP))
  70. {
  71. return false;
  72. }
  73. data_buffer[1] = DDRAM_ADR + LCD_LOWER_LINE;
  74. if (!twi_master_transfer(LCD_ADDR << 1, data_buffer, 2, TWI_ISSUE_STOP))
  75. return false;
  76. if (!twi_master_transfer(LCD_ADDR << 1, empty_str, 18, TWI_ISSUE_STOP))
  77. return false;
  78. return true;
  79. }
  80. bool nrf6350_lcd_set_contrast(uint8_t contrast)
  81. {
  82. nrf_delay_us(10000);
  83. data_buffer[0] = FUNC_SET;
  84. data_buffer[1] = 0x70 | contrast;
  85. return twi_master_transfer(LCD_ADDR << 1, data_buffer, 2, TWI_ISSUE_STOP);
  86. }
  87. bool nrf6350_lcd_on(void)
  88. {
  89. nrf_delay_us(10000);
  90. data_buffer[0] = FUNC_SET;
  91. data_buffer[1] = 0x0C;
  92. return twi_master_transfer(LCD_ADDR << 1, data_buffer, 2, TWI_ISSUE_STOP);
  93. }
  94. bool nrf6350_lcd_off(void)
  95. {
  96. nrf_delay_us(10000);
  97. data_buffer[0] = FUNC_SET;
  98. data_buffer[1] = 0x08;
  99. return twi_master_transfer(LCD_ADDR << 1, data_buffer, 2, TWI_ISSUE_STOP);
  100. }
  101. bool nrf6350_lcd_init(void)
  102. {
  103. if (!twi_master_init())
  104. {
  105. return false;
  106. }
  107. // Sometimes the first command doesn't get through, so we'll try
  108. // sending non-important "wake up" command first and don't care if it fails.
  109. (void)nrf6350_lcd_wake_up();
  110. if (!nrf6350_lcd_set_instruction(0x38)) // Function set.
  111. return false;
  112. if (!nrf6350_lcd_set_instruction(0x39)) // Choose two-line mode.
  113. return false;
  114. if (!nrf6350_lcd_set_instruction(0x14)) // Internal OSC frequency.
  115. return false;
  116. if (!nrf6350_lcd_set_contrast(LCD_CONTRAST_HIGH)) // Contrast set (low byte).
  117. return false;
  118. if (!nrf6350_lcd_set_instruction(0x5F)) // Power/ICON control/.
  119. return false;
  120. if (!nrf6350_lcd_set_instruction(0x6A)) // Follower control.
  121. return false;
  122. nrf_delay_us(200000); // Need to wait 200ms here according to datasheet.
  123. if (!nrf6350_lcd_on()) // Display ON.
  124. return false;
  125. if (!nrf6350_lcd_clear()) // Clear display.
  126. return false;
  127. return nrf6350_lcd_set_instruction(0x06); // Entry mode set.
  128. }
  129. bool nrf6350_lcd_write_string(const char *p_text, uint8_t size, uint8_t line, uint8_t pos)
  130. {
  131. uint8_t i;
  132. data_buffer[0] = FUNC_SET;
  133. data_buffer[1] = DDRAM_ADR + (pos + line);
  134. if (!twi_master_transfer(LCD_ADDR << 1, data_buffer, 2, TWI_ISSUE_STOP))
  135. return false;
  136. if (!twi_master_transfer(LCD_ADDR << 1, empty_str, 18 - pos, TWI_ISSUE_STOP))
  137. return false;
  138. data_buffer[0] = FUNC_SET;
  139. data_buffer[1] = DDRAM_ADR + (pos + line);
  140. if (!twi_master_transfer(LCD_ADDR << 1, data_buffer, 2, TWI_ISSUE_STOP))
  141. return false;
  142. data_buffer[0] = DDRAM_WR;
  143. for (i=0;i<size;i++)
  144. {
  145. if (i == LCD_LLEN)
  146. break;
  147. data_buffer[i + 1] = (uint8_t) * p_text++;
  148. }
  149. return twi_master_transfer(LCD_ADDR << 1, data_buffer, i + 1, TWI_ISSUE_STOP);
  150. }
  151. bool nrf6350_js_get_value(int8_t * val)
  152. {
  153. uint8_t js_data;
  154. if (!twi_master_transfer(JS_ADDR << 1 | TWI_READ_BIT, data_buffer, 1, TWI_ISSUE_STOP))
  155. return false;
  156. js_data = (~data_buffer[0] & 0x1D); // Select the useful bits.
  157. if ((js_data & 0x01) != 0) // Check joystick position.
  158. {
  159. val[X] = -1;
  160. }
  161. else if ((js_data & 0x10) != 0)
  162. {
  163. val[X] = 1;
  164. }
  165. else
  166. {
  167. val[X] = 0;
  168. }
  169. if ((js_data & 0x04) != 0)
  170. {
  171. val[Y] = 1;
  172. }
  173. else if ((js_data & 0x08) != 0)
  174. {
  175. val[Y] = -1;
  176. }
  177. else
  178. {
  179. val[Y] = 0;
  180. }
  181. return true;
  182. }
  183. bool nrf6350_js_get_status(uint8_t * js_state)
  184. {
  185. uint8_t js_data;
  186. if (!twi_master_transfer(JS_ADDR << 1 | TWI_READ_BIT, &js_data, 1, TWI_ISSUE_STOP))
  187. {
  188. return false;
  189. }
  190. js_data = ~js_data;
  191. *js_state = js_data & 0x1F;
  192. return true;
  193. }
  194. /** @brief First time communication with the development kit nRF6350 display will fail, this
  195. * returns false on timeout instead of attempting to recover.
  196. */
  197. static bool nrf6350_lcd_write_without_recovery(uint8_t * data,
  198. uint8_t data_length,
  199. bool issue_stop_condition)
  200. {
  201. uint32_t timeout = 20000; /* max loops to wait for EVENTS_TXDSENT event*/
  202. if (data_length == 0)
  203. {
  204. /* Return false for requesting data of size 0 */
  205. return false;
  206. }
  207. NRF_TWI1->TXD = *data++;
  208. NRF_TWI1->TASKS_STARTTX = 1;
  209. /** @snippet [TWI HW master write] */
  210. while (true)
  211. {
  212. while (NRF_TWI1->EVENTS_TXDSENT == 0 && (--timeout))
  213. {
  214. // Do nothing.
  215. }
  216. if (timeout == 0)
  217. {
  218. NRF_TWI1->EVENTS_STOPPED = 0;
  219. NRF_TWI1->TASKS_STOP = 1;
  220. /* Wait until stop sequence is sent */
  221. while (NRF_TWI1->EVENTS_STOPPED == 0)
  222. {
  223. // Do nothing.
  224. }
  225. /* Timeout before receiving event*/
  226. return false;
  227. }
  228. NRF_TWI1->EVENTS_TXDSENT = 0;
  229. if (--data_length == 0)
  230. {
  231. break;
  232. }
  233. NRF_TWI1->TXD = *data++;
  234. }
  235. /** @snippet [TWI HW master write] */
  236. if (issue_stop_condition)
  237. {
  238. NRF_TWI1->EVENTS_STOPPED = 0;
  239. NRF_TWI1->TASKS_STOP = 1;
  240. /* Wait until stop sequence is sent */
  241. while (NRF_TWI1->EVENTS_STOPPED == 0)
  242. {
  243. // Do nothing.
  244. }
  245. }
  246. return true;
  247. }
  248. /** @brief Function for transfer by twi_master.
  249. */
  250. bool nrf6350_lcd_wake_up(void)
  251. {
  252. uint8_t address = (LCD_ADDR << 1);
  253. uint8_t dummy_data[] = {0, 0, 0, 0};
  254. uint8_t dummy_data_length = 4;
  255. bool issue_stop_condition = 0;
  256. bool transfer_succeeded = false;
  257. NRF_TWI1->ADDRESS = (address >> 1);
  258. transfer_succeeded = nrf6350_lcd_write_without_recovery(dummy_data,
  259. dummy_data_length,
  260. issue_stop_condition);
  261. NRF_TWI1->EVENTS_ERROR = 0;
  262. return transfer_succeeded;
  263. }
  264. /*lint --flb "Leave library region" */