Advertisement
Guest User

driver source

a guest
Oct 25th, 2014
22
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.42 KB | None | 0 0
  1.  
  2. /*
  3. * About: A software driver for Hitachi LCD Controller HD44780.
  4. * Provide both 8 bit and 4 bit operation mode.
  5. * Optimized for 16MHz cpufreq.
  6. *
  7. * NatriX 2014
  8. */
  9.  
  10. #include "config.h"
  11. #include "global.h"
  12. #include "hd44780.h"
  13.  
  14.  
  15. .global lcd_init
  16. .global lcd_write_string
  17. .global lcd_send_instr
  18. .global lcd_send_data
  19. .global lcd_wait_if_busy
  20. #ifndef LCD_COM_DUMMY_READ
  21. .global lcd_get_address
  22. .global lcd_read_data
  23. #endif /* LCD_COM_DUMMY_READ */
  24.  
  25.  
  26. #define __r_tmp1 r18
  27.  
  28.  
  29. /*
  30. * void lcd_init( uint8_t flags );
  31. * Reset the LCD controller by instruction.
  32. */
  33. lcd_init:
  34.  
  35. /* Make sure they are 0V or high-Z */
  36. cbi LCD_COM_INSTR_PORT, LCD_COM_PIN_RS
  37. cbi LCD_COM_INSTR_PORT, LCD_COM_PIN_RW
  38. cbi LCD_COM_INSTR_PORT, LCD_COM_PIN_E
  39.  
  40. /* Set them to output low */
  41. sbi LCD_COM_INSTR_DDR, LCD_COM_PIN_RS
  42. sbi LCD_COM_INSTR_DDR, LCD_COM_PIN_RW
  43. sbi LCD_COM_INSTR_DDR, LCD_COM_PIN_E
  44.  
  45. #ifdef LCD_COM_4_BIT_MODE
  46. cbi LCD_COM_DATA_PORT, LCD_COM_PIN_DB4
  47. cbi LCD_COM_DATA_PORT, LCD_COM_PIN_DB5
  48. cbi LCD_COM_DATA_PORT, LCD_COM_PIN_DB6
  49. cbi LCD_COM_DATA_PORT, LCD_COM_PIN_DB7
  50.  
  51. sbi LCD_COM_DATA_DDR, LCD_COM_PIN_DB4
  52. sbi LCD_COM_DATA_DDR, LCD_COM_PIN_DB5
  53. sbi LCD_COM_DATA_DDR, LCD_COM_PIN_DB6
  54. sbi LCD_COM_DATA_DDR, LCD_COM_PIN_DB7
  55. #else
  56. out LCD_COM_DATA_PORT, __zero_reg__
  57. ldi __r_tmp1, 0xFF
  58. out LCD_COM_DATA_DDR, __r_tmp1
  59. #endif /* #ifdef LCD_COM_4_BIT_MODE */
  60.  
  61. /* save arg flags to stack */
  62. push r24
  63.  
  64. /* these values must not be changed
  65. very soon. */
  66. ;ldi rARG1, 0x30 ;FIXME
  67. clr r25
  68.  
  69. /* HD44780 Init by instruction */
  70. /* Step 1 */
  71. ldi r24, 60
  72. rcall delay_ms
  73.  
  74. /* Step 2 */
  75. ldi r24, 0x30
  76. #ifdef LCD_COM_4_BIT_MODE
  77. rcall lcd_send_first_nibble
  78. #else
  79. rcall lcd_send_instr_no_check
  80. #endif /* LCD_COM_4_BIT_MODE */
  81.  
  82. /* Step 3 */
  83. ldi r24, 10
  84. rcall delay_ms
  85. ldi r24, 0x30
  86. #ifdef LCD_COM_4_BIT_MODE
  87. rcall lcd_send_first_nibble
  88. #else
  89. rcall lcd_send_instr_no_check
  90. #endif /* LCD_COM_4_BIT_MODE */
  91.  
  92. /* Step 4 */
  93. rcall delay_1ms
  94. ldi r24, 0x30; FIXME needed?
  95. #ifdef LCD_COM_4_BIT_MODE
  96. rcall lcd_send_first_nibble
  97. #else
  98. rcall lcd_send_instr_no_check
  99. #endif /* LCD_COM_4_BIT_MODE */
  100.  
  101. /* Step 5 */
  102. ldi r24, 10; FIXME remove?
  103. rcall delay_ms
  104.  
  105. /* Step 6 - Setting the display lines and fonts. These cannot
  106. be changed after this point, so we gonna make them
  107. accesible via arguments rARG1, or default as one line and 5x8 font. */
  108. #ifdef LCD_COM_4_BIT_MODE
  109. /* Step 6' -- extrastep for 4 bit mode */
  110. ldi r24, 0x20
  111. rcall lcd_send_first_nibble
  112. ldi r24, 10
  113. rcall delay_ms
  114.  
  115. /* get the saved flags */
  116. pop r24
  117. ori r24, (LCD_INSTR_FUNCTION_SET)
  118. rcall lcd_send_instr_no_check
  119. #else
  120. /* get the saved flags */
  121. pop r24
  122.  
  123. ori r24, (LCD_INSTR_FUNCTION_SET | LCD_SET_8_BITS)
  124. rcall lcd_send_instr_no_check
  125. #endif /* #ifdef LCD_COM_4_BIT_MODE */
  126.  
  127. /* Step 7 */
  128. ldi r24, 10
  129. rcall delay_ms
  130. ldi r24, LCD_INSTR_DISPLAY_CTRL
  131. rcall lcd_send_instr_no_check
  132.  
  133. /* Step 9 */
  134. ldi r24, 10
  135. rcall delay_ms
  136. ldi r24, LCD_INSTR_CLEAR_DISPLAY
  137. rcall lcd_send_instr_no_check
  138.  
  139. /* Step 10 */
  140. ldi r24, 10
  141. rcall delay_ms
  142. ldi r24, (LCD_INSTR_ENTRY_MODE_SET | LCD_SET_INCREMENT)
  143. rcall lcd_send_instr_no_check
  144. /* Done init the LCD by instruction */
  145. /* Turn display on */
  146. ldi r24, 10
  147. rcall delay_ms
  148. ldi r24, (LCD_INSTR_DISPLAY_CTRL | LCD_SET_DISPLAY_ON)
  149. rcall lcd_send_instr_no_check
  150. ret
  151.  
  152.  
  153.  
  154. /*
  155. * Multiple functions used to write data/instructions to
  156. * LCD controller.
  157. * TODO: save T flag ?
  158. */
  159. #ifdef LCD_COM_4_BIT_MODE
  160. /*
  161. * void lcd_send_first_nibble( unsigned char byte );
  162. */
  163. lcd_send_first_nibble:
  164. set
  165. rjmp again4
  166. #endif /* LCD_COM_4_BIT_MODE */
  167. /*
  168. * void lcd_send_data( unsigned char byte );
  169. */
  170. lcd_send_data:
  171. /* lcd_wait_if_busy will modify our r24 register
  172. which is uchar byte arg. so must be saved */
  173. mov __tmp_reg__, r24
  174. rcall lcd_wait_if_busy
  175. mov r24, __tmp_reg__
  176. rjmp lcd_send_data_no_check
  177. /*
  178. * void lcd_send_instr( unsigned char byte );
  179. */
  180. lcd_send_instr:
  181. /* lcd_wait_if_busy will modify our r24 register
  182. which is uchar byte arg. so must be saved */
  183. mov __tmp_reg__, r24
  184. rcall lcd_wait_if_busy
  185. mov r24, __tmp_reg__
  186. /*
  187. * void lcd_send_instr_no_check( unsigned char byte );
  188. */
  189. lcd_send_instr_no_check:
  190. rjmp 1f
  191. /*
  192. * void lcd_send_data_no_check( unsigned char byte );
  193. */
  194. lcd_send_data_no_check:
  195. sbi LCD_COM_INSTR_PORT, LCD_COM_PIN_RS
  196. #ifdef LCD_COM_4_BIT_MODE
  197. 1: clt /* T flag used in 4bit mode */
  198. /* write data 4 */
  199. again4: sbrc r24, 7
  200. sbi LCD_COM_DATA_PORT, LCD_COM_PIN_DB7
  201. sbrc r24, 6
  202. sbi LCD_COM_DATA_PORT, LCD_COM_PIN_DB6
  203. sbrc r24, 5
  204. sbi LCD_COM_DATA_PORT, LCD_COM_PIN_DB5
  205. sbrc r24, 4
  206. sbi LCD_COM_DATA_PORT, LCD_COM_PIN_DB4
  207. #else
  208. /* write data 8 */
  209. 1: out LCD_COM_DATA_PORT, r24
  210. #endif /* LCD_COM_4_BIT_MODE */
  211.  
  212. /* set E on */
  213. sbi LCD_COM_INSTR_PORT, LCD_COM_PIN_E
  214. nop
  215. nop
  216. #if CPU_FREQ > 4000000
  217. nop
  218. nop
  219. nop
  220. #endif /* CPU_FREQ > 4000000 */
  221.  
  222. /* turn E off */
  223. cbi LCD_COM_INSTR_PORT, LCD_COM_PIN_E
  224. #ifdef LCD_COM_4_BIT_MODE
  225. /* erase data 4 */
  226. cbi LCD_COM_DATA_PORT, LCD_COM_PIN_DB7
  227. cbi LCD_COM_DATA_PORT, LCD_COM_PIN_DB6
  228. cbi LCD_COM_DATA_PORT, LCD_COM_PIN_DB5
  229. cbi LCD_COM_DATA_PORT, LCD_COM_PIN_DB4
  230.  
  231. brts end4
  232. /* this sould happen once */
  233. swap r24
  234. set
  235. rjmp again4
  236. #else
  237. /* erase data 8 */
  238. out LCD_COM_DATA_PORT, __zero_reg__
  239. #endif /* LCD_COM_4_BIT_MOD */
  240. /* turn RS off */
  241. end4: cbi LCD_COM_INSTR_PORT, LCD_COM_PIN_RS
  242. ret
  243.  
  244.  
  245.  
  246. #ifdef LCD_COM_DUMMY_READ
  247. /*
  248. * void lcd_wait_if_busy( void );
  249. */
  250. lcd_wait_if_busy:
  251. ldi r24, 5
  252. rcall delay_ms
  253. ret
  254. #else
  255. /* FIXME: este ok cand folosesc comunicatie de 4 biti cu pinii 4-7
  256. din mcu indiferent de ordine, dar cand folosesc pini de la 3 la 6
  257. am o problema in functia de read, ramane hangedup cu RW pe on si E
  258. intermitent, probabil ceva gen data reordering nu este facuta cum
  259. trebuie */
  260.  
  261.  
  262. /*
  263. * unsigned char lcd_read_data( void );
  264. * Reads a byte from LCD cursor.
  265. */
  266. lcd_read_data:
  267. rcall lcd_wait_if_busy
  268. sbi LCD_COM_INSTR_PORT, LCD_COM_PIN_RS
  269.  
  270. /*
  271. * unsigned char lcd_wait_if_busy( void );
  272. * Return when busy flag is off and it also reads
  273. * the cursor address and store it in the rRET register
  274. * as returned value.
  275. */
  276. lcd_wait_if_busy:
  277. lcd_get_address: /* just an alias */
  278. #ifdef LCD_COM_4_BIT_MODE
  279. /* set DATA PORT to input 4 bit mode */
  280. cbi LCD_COM_DATA_DDR, LCD_COM_PIN_DB4
  281. cbi LCD_COM_DATA_DDR, LCD_COM_PIN_DB5
  282. cbi LCD_COM_DATA_DDR, LCD_COM_PIN_DB6
  283. cbi LCD_COM_DATA_DDR, LCD_COM_PIN_DB7
  284. #else /* LCD_COM_4_BIT_MODE */
  285. /* set DATA PORT to input 8 bit mode */
  286. out LCD_COM_DATA_DDR, __zero_reg__
  287. #endif /* LCD_COM_4_BIT_MODE */
  288. nop /* nop for sync */
  289. /* set RW on */
  290. sbi LCD_COM_INSTR_PORT, LCD_COM_PIN_RW
  291.  
  292. check_again:
  293. #ifdef LCD_COM_4_BIT_MODE
  294. /* clear T flag and return
  295. retister */
  296. clt
  297. eor r24, r24
  298. read_2nd_nibble:
  299. #endif /* LCD_COM_4_BIT_MODE */
  300.  
  301. /* set E on */
  302. sbi LCD_COM_INSTR_PORT, LCD_COM_PIN_E
  303. nop
  304. nop
  305. nop
  306. /* Using 16Mhz, data from HD44780 should be
  307. available. Just NOP for pin sync */
  308. nop
  309.  
  310. #ifdef LCD_COM_4_BIT_MODE
  311. /* read data from LCD 4 bit mode */
  312. sbic LCD_COM_DATA_PIN, LCD_COM_PIN_DB7
  313. sbr r24, 0b00001000
  314. sbic LCD_COM_DATA_PIN, LCD_COM_PIN_DB6
  315. sbr r24, 0b00000100
  316. sbic LCD_COM_DATA_PIN, LCD_COM_PIN_DB5
  317. sbr r24, 0b00000010
  318. sbic LCD_COM_DATA_PIN, LCD_COM_PIN_DB4
  319. sbr r24, 0b00000001
  320. #else /* LCD_COM_4_BIT_MODE */
  321. /* read data from LCD 8 bit mode */
  322. in r24, LCD_COM_DATA_PIN
  323. #endif /* LCD_COM_4_BIT_MODE */
  324.  
  325. /* turn E off */
  326. cbi LCD_COM_INSTR_PORT, LCD_COM_PIN_E
  327.  
  328. #ifdef LCD_COM_4_BIT_MODE
  329. /* read second nibble */
  330. brts done_4bit
  331. nop /* little delay. E must be off >250ns */
  332. swap r24
  333. set
  334. rjmp read_2nd_nibble
  335. done_4bit:
  336. #endif /* LCD_COM_4_BIT_MODE */
  337.  
  338. /* lcd_read_data or lcd_wait_if_busy ? */
  339. sbic LCD_COM_INSTR_PORT, LCD_COM_PIN_RS
  340. rjmp 1f
  341.  
  342. /* check the busy bit */
  343. sbrc r24, LCD_COM_PIN_DB7
  344. rjmp check_again
  345.  
  346. /* turn RW off */
  347. 1: cbi LCD_COM_INSTR_PORT, LCD_COM_PIN_RW
  348. /* turn RS off */
  349. cbi LCD_COM_INSTR_PORT, LCD_COM_PIN_RS
  350.  
  351. #ifdef LCD_COM_4_BIT_MODE
  352. /* set pins again as output 4 bit mode */
  353. sbi LCD_COM_DATA_DDR, LCD_COM_PIN_DB4
  354. sbi LCD_COM_DATA_DDR, LCD_COM_PIN_DB5
  355. sbi LCD_COM_DATA_DDR, LCD_COM_PIN_DB6
  356. sbi LCD_COM_DATA_DDR, LCD_COM_PIN_DB7
  357. #else /* LCD_COM_4_BIT_MODE */
  358. /* set pins again as output 8 bit mode */
  359. ldi __r_tmp1, 0xFF
  360. out LCD_COM_DATA_DDR, __r_tmp1
  361. #endif /* LCD_COM_4_BIT_MODE */
  362. ret
  363. #endif /* LCD_COM_DUMMY_READ */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement