nrf6350.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. /* Copyright (c) 2008-2012 Nordic Semiconductor. All Rights Reserved.
  2. *
  3. * The information contained herein is property of Nordic Semiconductor ASA.
  4. * Terms and conditions of usage are described in detail in NORDIC
  5. * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
  6. *
  7. * Licensees are granted free, non-transferable use of the information. NO
  8. * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
  9. * the file.
  10. *
  11. */
  12. #include "nrf6350.h"
  13. #include "nrf_delay.h"
  14. #include "twi_master.h"
  15. /*lint ++flb "Enter library region" */
  16. #define DDRAM_ADR 0x80 //!< Write to DDRAM AC
  17. #define DDRAM_WR 0x40 //!< Write to DDRAM
  18. #define FUNC_SET 0x00 //!< Enter LCD Function settings
  19. #define LCD_ADDR 0x3E //!< LCD display adr
  20. #define JS_ADDR 0x3F //!< Joystick adr
  21. #define X 0 //!< X direction in pos 0 of joystick array
  22. #define Y 1 //!< Y direction in pos 1 of joystick array
  23. //static void nrf6350_nrf6350_lcd_set_instruction(uint8_t instr);
  24. #define BUF_LEN 32 //!< LCD data buffer length
  25. static uint8_t data_buffer[BUF_LEN]; //!< LCD data buffer
  26. static uint8_t empty_str[18] = {DDRAM_WR, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '}; //!< Blank line
  27. static bool nrf6350_lcd_set_instruction(uint8_t instr)
  28. {
  29. nrf_delay_us(10000);
  30. data_buffer[0] = FUNC_SET;
  31. data_buffer[1] = instr;
  32. return twi_master_transfer(LCD_ADDR << 1, data_buffer, 2, TWI_ISSUE_STOP);
  33. }
  34. bool nrf6350_lcd_clear(void)
  35. {
  36. nrf_delay_us(10000);
  37. data_buffer[0] = FUNC_SET;
  38. data_buffer[1] = (uint8_t)(DDRAM_ADR + LCD_UPPER_LINE);
  39. if (!twi_master_transfer(LCD_ADDR << 1, data_buffer, 2, TWI_ISSUE_STOP))
  40. return false;
  41. if (!twi_master_transfer(LCD_ADDR << 1, empty_str, 18, TWI_ISSUE_STOP))
  42. {
  43. return false;
  44. }
  45. data_buffer[1] = DDRAM_ADR + LCD_LOWER_LINE;
  46. if (!twi_master_transfer(LCD_ADDR << 1, data_buffer, 2, TWI_ISSUE_STOP))
  47. return false;
  48. if (!twi_master_transfer(LCD_ADDR << 1, empty_str, 18, TWI_ISSUE_STOP))
  49. return false;
  50. return true;
  51. }
  52. bool nrf6350_lcd_set_contrast(uint8_t contrast)
  53. {
  54. nrf_delay_us(10000);
  55. data_buffer[0] = FUNC_SET;
  56. data_buffer[1] = 0x70 | contrast;
  57. return twi_master_transfer(LCD_ADDR << 1, data_buffer, 2, TWI_ISSUE_STOP);
  58. }
  59. bool nrf6350_lcd_on(void)
  60. {
  61. nrf_delay_us(10000);
  62. data_buffer[0] = FUNC_SET;
  63. data_buffer[1] = 0x0C;
  64. return twi_master_transfer(LCD_ADDR << 1, data_buffer, 2, TWI_ISSUE_STOP);
  65. }
  66. bool nrf6350_lcd_off(void)
  67. {
  68. nrf_delay_us(10000);
  69. data_buffer[0] = FUNC_SET;
  70. data_buffer[1] = 0x08;
  71. return twi_master_transfer(LCD_ADDR << 1, data_buffer, 2, TWI_ISSUE_STOP);
  72. }
  73. bool nrf6350_lcd_init(void)
  74. {
  75. if (!twi_master_init())
  76. {
  77. return false;
  78. }
  79. // Sometimes the first command doesn't get through, so we'll try
  80. // sending non-important "wake up" command first and don't care if it fails.
  81. (void)nrf6350_lcd_wake_up();
  82. if (!nrf6350_lcd_set_instruction(0x38)) // Function set.
  83. return false;
  84. if (!nrf6350_lcd_set_instruction(0x39)) // Choose two-line mode.
  85. return false;
  86. if (!nrf6350_lcd_set_instruction(0x14)) // Internal OSC frequency.
  87. return false;
  88. if (!nrf6350_lcd_set_contrast(LCD_CONTRAST_HIGH)) // Contrast set (low byte).
  89. return false;
  90. if (!nrf6350_lcd_set_instruction(0x5F)) // Power/ICON control/.
  91. return false;
  92. if (!nrf6350_lcd_set_instruction(0x6A)) // Follower control.
  93. return false;
  94. nrf_delay_us(200000); // Need to wait 200ms here according to datasheet.
  95. if (!nrf6350_lcd_on()) // Display ON.
  96. return false;
  97. if (!nrf6350_lcd_clear()) // Clear display.
  98. return false;
  99. return nrf6350_lcd_set_instruction(0x06); // Entry mode set.
  100. }
  101. bool nrf6350_lcd_write_string(const char *p_text, uint8_t size, uint8_t line, uint8_t pos)
  102. {
  103. uint8_t i;
  104. data_buffer[0] = FUNC_SET;
  105. data_buffer[1] = DDRAM_ADR + (pos + line);
  106. if (!twi_master_transfer(LCD_ADDR << 1, data_buffer, 2, TWI_ISSUE_STOP))
  107. return false;
  108. if (!twi_master_transfer(LCD_ADDR << 1, empty_str, 18 - pos, TWI_ISSUE_STOP))
  109. return false;
  110. data_buffer[0] = FUNC_SET;
  111. data_buffer[1] = DDRAM_ADR + (pos + line);
  112. if (!twi_master_transfer(LCD_ADDR << 1, data_buffer, 2, TWI_ISSUE_STOP))
  113. return false;
  114. data_buffer[0] = DDRAM_WR;
  115. for (i=0;i<size;i++)
  116. {
  117. if (i == LCD_LLEN)
  118. break;
  119. data_buffer[i+1] = (uint8_t)*p_text++;
  120. }
  121. return twi_master_transfer(LCD_ADDR << 1, data_buffer, i+1, TWI_ISSUE_STOP);
  122. }
  123. bool nrf6350_js_get_value(int8_t * val)
  124. {
  125. uint8_t js_data;
  126. if (!twi_master_transfer(JS_ADDR << 1 | TWI_READ_BIT, data_buffer, 1, TWI_ISSUE_STOP))
  127. return false;
  128. js_data = (~data_buffer[0] & 0x1D); // Select the useful bits.
  129. if ((js_data & 0x01) != 0) // Check joystick position.
  130. {
  131. val[X] = -1;
  132. }
  133. else if ((js_data & 0x10) != 0)
  134. {
  135. val[X] = 1;
  136. }
  137. else
  138. {
  139. val[X] = 0;
  140. }
  141. if ((js_data & 0x04) != 0)
  142. {
  143. val[Y] = 1;
  144. }
  145. else if ((js_data & 0x08) != 0)
  146. {
  147. val[Y] = -1;
  148. }
  149. else
  150. {
  151. val[Y] = 0;
  152. }
  153. return true;
  154. }
  155. bool nrf6350_js_get_status(uint8_t * js_state)
  156. {
  157. uint8_t js_data;
  158. if (!twi_master_transfer(JS_ADDR << 1 | TWI_READ_BIT, &js_data, 1, TWI_ISSUE_STOP))
  159. {
  160. return false;
  161. }
  162. js_data = ~js_data;
  163. *js_state = js_data & 0x1F;
  164. return true;
  165. }
  166. /** @brief First time communication with the development kit nRF6350 display will fail, this
  167. * returns false on timeout instead of attempting to recover.
  168. */
  169. static bool nrf6350_lcd_write_without_recovery(uint8_t * data,
  170. uint8_t data_length,
  171. bool issue_stop_condition)
  172. {
  173. uint32_t timeout = 20000; /* max loops to wait for EVENTS_TXDSENT event*/
  174. if (data_length == 0)
  175. {
  176. /* Return false for requesting data of size 0 */
  177. return false;
  178. }
  179. NRF_TWI1->TXD = *data++;
  180. NRF_TWI1->TASKS_STARTTX = 1;
  181. /** @snippet [TWI HW master write] */
  182. while (true)
  183. {
  184. while (NRF_TWI1->EVENTS_TXDSENT == 0 && (--timeout))
  185. {
  186. // Do nothing.
  187. }
  188. if (timeout == 0)
  189. {
  190. NRF_TWI1->EVENTS_STOPPED = 0;
  191. NRF_TWI1->TASKS_STOP = 1;
  192. /* Wait until stop sequence is sent */
  193. while (NRF_TWI1->EVENTS_STOPPED == 0)
  194. {
  195. // Do nothing.
  196. }
  197. /* Timeout before receiving event*/
  198. return false;
  199. }
  200. NRF_TWI1->EVENTS_TXDSENT = 0;
  201. if (--data_length == 0)
  202. {
  203. break;
  204. }
  205. NRF_TWI1->TXD = *data++;
  206. }
  207. /** @snippet [TWI HW master write] */
  208. if (issue_stop_condition)
  209. {
  210. NRF_TWI1->EVENTS_STOPPED = 0;
  211. NRF_TWI1->TASKS_STOP = 1;
  212. /* Wait until stop sequence is sent */
  213. while (NRF_TWI1->EVENTS_STOPPED == 0)
  214. {
  215. // Do nothing.
  216. }
  217. }
  218. return true;
  219. }
  220. /** @brief Function for transfer by twi_master.
  221. */
  222. bool nrf6350_lcd_wake_up(void)
  223. {
  224. uint8_t address = (LCD_ADDR << 1);
  225. uint8_t dummy_data[] = {0, 0, 0, 0};
  226. uint8_t dummy_data_length = 4;
  227. bool issue_stop_condition = 0;
  228. bool transfer_succeeded = false;
  229. NRF_TWI1->ADDRESS = (address >> 1);
  230. transfer_succeeded = nrf6350_lcd_write_without_recovery(dummy_data,
  231. dummy_data_length,
  232. issue_stop_condition);
  233. NRF_TWI1->EVENTS_ERROR = 0;
  234. return transfer_succeeded;
  235. }
  236. /*lint --flb "Leave library region" */