Details | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 34 | jlesech | 1 | /**************************************************************************//** |
| 2 | * \brief Snootlab Deuligne library |
||
| 3 | * \author Copyright (C) 2012 Julien Le Sech - www.idreammicro.com |
||
| 4 | * \version 1.0 |
||
| 5 | * \date 20121026 |
||
| 6 | * |
||
| 7 | * This file is part of the iDreamMicro library. |
||
| 8 | * |
||
| 9 | * This library is free software: you can redistribute it and/or modify it under |
||
| 10 | * the terms of the GNU Lesser General Public License as published by the Free |
||
| 11 | * Software Foundation, either version 3 of the License, or (at your option) any |
||
| 12 | * later version. |
||
| 13 | * |
||
| 14 | * This library is distributed in the hope that it will be useful, but WITHOUT |
||
| 15 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
||
| 16 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more |
||
| 17 | * details. |
||
| 18 | * |
||
| 19 | * You should have received a copy of the GNU Lesser General Public License |
||
| 20 | * along with this program. If not, see http://www.gnu.org/licenses/ |
||
| 21 | ******************************************************************************/ |
||
| 22 | |||
| 23 | /**************************************************************************//** |
||
| 24 | * \headerfile deuligne.c |
||
| 25 | ******************************************************************************/ |
||
| 26 | |||
| 27 | /****************************************************************************** |
||
| 28 | * Header file inclusions. |
||
| 29 | ******************************************************************************/ |
||
| 30 | |||
| 31 | #include "../deuligne.h" |
||
| 32 | |||
| 33 | #include <adc/adc.h> |
||
| 34 | #include <mcp23008/mcp23008.h> |
||
| 35 | |||
| 36 | #include <util/delay.h> |
||
| 37 | |||
| 38 | #include <assert.h> |
||
| 39 | #include <stdbool.h> |
||
| 40 | #include <stdint.h> |
||
| 41 | #include <stdlib.h> |
||
| 42 | |||
| 43 | /****************************************************************************** |
||
| 44 | * Private macro definitions. |
||
| 45 | ******************************************************************************/ |
||
| 46 | |||
| 47 | /**************************************************************************//** |
||
| 48 | * \def DEULIGNE__HARDWARE_ADDRESS |
||
| 49 | * \brief MCP23008 hardware address. Pins A0 to A3. |
||
| 50 | ******************************************************************************/ |
||
| 51 | #define DEULIGNE__HARDWARE_ADDRESS 0x07 |
||
| 52 | |||
| 53 | #define DEULIGNE__GPIO_E 4 |
||
| 54 | #define DEULIGNE__GPIO_RW 5 |
||
| 55 | #define DEULIGNE__GPIO_RS 6 |
||
| 56 | #define DEULIGNE__GPIO_BACKLIGHT 7 |
||
| 57 | |||
| 58 | /**************************************************************************//** |
||
| 59 | * \def LCD__CMD_CLEAR_DISPLAY |
||
| 60 | * \brief Clear display. |
||
| 61 | ******************************************************************************/ |
||
| 62 | #define LCD__CMD_CLEAR_DISPLAY 0x01 |
||
| 63 | |||
| 64 | /**************************************************************************//** |
||
| 65 | * \def LCD__CMD_RETURN_HOME |
||
| 66 | * \brief Return Home (execution time = 1.52 ms). |
||
| 67 | ******************************************************************************/ |
||
| 68 | #define LCD__CMD_RETURN_HOME 0x02 |
||
| 69 | |||
| 70 | // Function set (execution time = 37 s). |
||
| 71 | #define LCD__CMD_FUNCTION_SET 0x20 |
||
| 72 | #define LCD__CMD_DATA_LENGTH_4_BIT 0x00 |
||
| 73 | #define LCD__CMD_DATA_LENGTH_8_BIT 0x10 |
||
| 74 | #define LCD__CMD_DISPLAY_LINE_1 0x00 |
||
| 75 | #define LCD__CMD_DISPLAY_LINE_2 0x08 |
||
| 76 | #define LCD__CMD_CHARACTER_FONT_5x8_DOTS 0x00 |
||
| 77 | #define LCD__CMD_CHARACTER_FONT_5x10_DOTS 0x04 |
||
| 78 | |||
| 79 | // Set entry mode (execution time = 37 s). |
||
| 80 | #define LCD__CMD_ENTRY_MODE_SET 0x04 |
||
| 81 | #define LCD__CMD_INCREMENT_ADDRESS 0x02 |
||
| 82 | #define LCD__CMD_DECREMENT_ADDRESS 0x00 |
||
| 83 | #define LCD__CMD_DISPLAY_SHIFT_DISABLED 0x00 |
||
| 84 | #define LCD__CMD_DISPLAY_SHIFT_RIGHT 0x01 |
||
| 85 | #define LCD__CMD_DISPLAY_SHIFT_LEFT 0x03 |
||
| 86 | |||
| 87 | // Display on/off control (execution time = 37 s). |
||
| 88 | #define LCD__CMD_DISPLAY_CONTROL 0x08 |
||
| 89 | #define LCD__CMD_ENABLE_DISPLAY 0x04 |
||
| 90 | #define LCD__CMD_DISABLE_DISPLAY 0x00 |
||
| 91 | #define LCD__CMD_ENABLE_CURSOR_DISPLAY 0x02 |
||
| 92 | #define LCD__CMD_DISABLE_CURSOR_DISPLAY 0x00 |
||
| 93 | #define LCD__CMD_ENABLE_CURSOR_BLINK 0x01 |
||
| 94 | #define LCD__CMD_DISABLE_CURSOR_BLINK 0x00 |
||
| 95 | |||
| 96 | // Cursor or display shift (execution time = 37 s). |
||
| 97 | #define LCD__CMD_CURSOR_OR_DISPLAY_SHIFT 0x10 |
||
| 98 | #define LCD__CMD_SHIFT_CURSOR 0x00 |
||
| 99 | #define LCD__CMD_SHIFT_DISPLAY 0x08 |
||
| 100 | #define LCD__CMD_SHIFT_RIGHT 0x04 |
||
| 101 | #define LCD__CMD_SHIFT_LEFT 0x00 |
||
| 102 | |||
| 103 | // CGRAM address. |
||
| 104 | #define LCD__CMD_SET_CGRAM_ADDRESS 0x40 |
||
| 105 | |||
| 106 | // DDRAM address. |
||
| 107 | #define LCD__CMD_SET_DDRAM_ADDRESS 0x80 |
||
| 108 | |||
| 109 | // Line addresses. |
||
| 110 | #define LCD__LINE_1_ADDRESS 0x40 |
||
| 111 | #define LCD__LINE_2_ADDRESS 0x80 |
||
| 112 | #define LCD__LINE_3_ADDRESS 0x54 |
||
| 113 | #define LCD__LINE_4_ADDRESS 0x94 |
||
| 114 | |||
| 115 | /****************************************************************************** |
||
| 116 | * Private function prototypes. |
||
| 117 | ******************************************************************************/ |
||
| 118 | |||
| 119 | /**************************************************************************//** |
||
| 120 | * \fn static void deuligne__write_command(uint8_t command) |
||
| 121 | * |
||
| 122 | * \brief Write a command on LCD port. |
||
| 123 | * |
||
| 124 | * \param command Command to write. |
||
| 125 | ******************************************************************************/ |
||
| 126 | static |
||
| 127 | void |
||
| 128 | deuligne__write_command |
||
| 129 | ( |
||
| 130 | uint8_t command |
||
| 131 | ); |
||
| 132 | |||
| 133 | /**************************************************************************//** |
||
| 134 | * \fn static void deuligne__write_byte(uint8_t data) |
||
| 135 | * |
||
| 136 | * \brief Write a byte on LCD port. |
||
| 137 | * |
||
| 138 | * \param data Byte to write. |
||
| 139 | ******************************************************************************/ |
||
| 140 | static |
||
| 141 | void |
||
| 142 | deuligne__write_byte |
||
| 143 | ( |
||
| 144 | uint8_t data |
||
| 145 | ); |
||
| 146 | |||
| 147 | /**************************************************************************//** |
||
| 148 | * \fn static void deuligne__write_high_nibble(uint8_t data) |
||
| 149 | * |
||
| 150 | * \brief Write the high nibble of a byte on LCD port. |
||
| 151 | * |
||
| 152 | * \param data Byte which write high nibble. |
||
| 153 | ******************************************************************************/ |
||
| 154 | static |
||
| 155 | void |
||
| 156 | deuligne__write_high_nibble |
||
| 157 | ( |
||
| 158 | uint8_t data |
||
| 159 | ); |
||
| 160 | |||
| 161 | /**************************************************************************//** |
||
| 162 | * \fn static void deuligne__enable_data(void) |
||
| 163 | * |
||
| 164 | * \brief Enable data on LCD port. |
||
| 165 | ******************************************************************************/ |
||
| 166 | static |
||
| 167 | void |
||
| 168 | deuligne__enable_data |
||
| 169 | ( |
||
| 170 | void |
||
| 171 | ); |
||
| 172 | |||
| 173 | /****************************************************************************** |
||
| 174 | * Private constant definitions. |
||
| 175 | ******************************************************************************/ |
||
| 176 | |||
| 177 | /**************************************************************************//** |
||
| 178 | * |
||
| 179 | ******************************************************************************/ |
||
| 180 | static const uint16_t deuligne__adc_values[] = |
||
| 181 | { |
||
| 182 | [DEULIGNE__KEY__RIGHT] = 50, |
||
| 183 | [DEULIGNE__KEY__UP] = 190, |
||
| 184 | [DEULIGNE__KEY__DOWN] = 400, |
||
| 185 | [DEULIGNE__KEY__LEFT] = 540, |
||
| 186 | [DEULIGNE__KEY__SELECT] = 770, |
||
| 187 | [DEULIGNE__KEY__NONE] = 1024 |
||
| 188 | }; |
||
| 189 | |||
| 190 | /****************************************************************************** |
||
| 191 | * Public function definitions. |
||
| 192 | ******************************************************************************/ |
||
| 193 | |||
| 194 | /**************************************************************************//** |
||
| 195 | * \fn void deuligne__initialize(void) |
||
| 196 | * |
||
| 197 | * \brief Initialize Deuligne. |
||
| 198 | ******************************************************************************/ |
||
| 199 | void |
||
| 200 | deuligne__initialize |
||
| 201 | ( |
||
| 202 | void |
||
| 203 | ){ |
||
| 204 | // Initialize MCP23008. |
||
| 205 | mcp23008__initialize(DEULIGNE__HARDWARE_ADDRESS); |
||
| 206 | |||
| 207 | // Configure all GPIOs in output. |
||
| 208 | mcp23008__configure_port(0x00); |
||
| 209 | |||
| 210 | mcp23008__set_pin_level(DEULIGNE__GPIO_RW, MCP23008__LEVEL__LOW); |
||
| 211 | |||
| 212 | // Wait for LCD display power-up initialization. |
||
| 213 | _delay_ms(45); |
||
| 214 | |||
| 215 | // Initialize LCD display. |
||
| 216 | |||
| 217 | // Set interface. |
||
| 218 | deuligne__write_high_nibble(LCD__CMD_FUNCTION_SET | LCD__CMD_DATA_LENGTH_8_BIT); |
||
| 219 | deuligne__write_high_nibble(LCD__CMD_FUNCTION_SET | LCD__CMD_DATA_LENGTH_8_BIT); |
||
| 220 | deuligne__write_high_nibble(LCD__CMD_FUNCTION_SET | LCD__CMD_DATA_LENGTH_8_BIT); |
||
| 221 | deuligne__write_high_nibble(LCD__CMD_FUNCTION_SET | LCD__CMD_DATA_LENGTH_4_BIT); |
||
| 222 | |||
| 223 | // Set function. |
||
| 224 | deuligne__set_function(DEULIGNE__DISPLAY_LINE_2, DEULIGNE__CHARACTER_FONT_5x8_DOTS); |
||
| 225 | |||
| 226 | // Set entry mode. |
||
| 227 | deuligne__set_entry_mode(DEULIGNE__INCREMENT_ADDRESS, DEULIGNE__DISPLAY_SHIFT_DISABLED); |
||
| 228 | |||
| 229 | // Clear display. |
||
| 230 | deuligne__clear_display(); |
||
| 231 | |||
| 232 | // Initialize ADC. |
||
| 233 | adc__single_channel_initialize(ADC__CHANNEL_0); |
||
| 234 | } |
||
| 235 | |||
| 236 | /**************************************************************************//** |
||
| 237 | * \fn void deuligne__switch_on_backlight(void) |
||
| 238 | * |
||
| 239 | * \brief Switch on backlight. |
||
| 240 | ******************************************************************************/ |
||
| 241 | void |
||
| 242 | deuligne__switch_on_backlight |
||
| 243 | ( |
||
| 244 | void |
||
| 245 | ){ |
||
| 246 | mcp23008__set_pin_level(DEULIGNE__GPIO_BACKLIGHT, MCP23008__LEVEL__HIGH); |
||
| 247 | } |
||
| 248 | |||
| 249 | /**************************************************************************//** |
||
| 250 | * \fn void deuligne__switch_off_backlight(void) |
||
| 251 | * |
||
| 252 | * \brief Switch off backlight. |
||
| 253 | ******************************************************************************/ |
||
| 254 | void |
||
| 255 | deuligne__switch_off_backlight |
||
| 256 | ( |
||
| 257 | void |
||
| 258 | ){ |
||
| 259 | mcp23008__set_pin_level(DEULIGNE__GPIO_BACKLIGHT, MCP23008__LEVEL__LOW); |
||
| 260 | } |
||
| 261 | |||
| 262 | /**************************************************************************//** |
||
| 263 | * \fn void deuligne__set_function( |
||
| 264 | * deuligne__display_line_t display_line, |
||
| 265 | * deuligne__character_font_t character_font) |
||
| 266 | * |
||
| 267 | * \brief Set the number of lines available on LCD display and the character font. |
||
| 268 | * |
||
| 269 | * \param display_line number of lines |
||
| 270 | * \param character_font character font |
||
| 271 | ******************************************************************************/ |
||
| 272 | void |
||
| 273 | deuligne__set_function |
||
| 274 | ( |
||
| 275 | deuligne__display_line_t display_line, |
||
| 276 | deuligne__character_font_t character_font |
||
| 277 | ){ |
||
| 278 | uint8_t command = LCD__CMD_FUNCTION_SET; |
||
| 279 | |||
| 280 | switch (display_line) |
||
| 281 | { |
||
| 282 | case DEULIGNE__DISPLAY_LINE_1: |
||
| 283 | { |
||
| 284 | command |= LCD__CMD_DISPLAY_LINE_1; |
||
| 285 | } |
||
| 286 | break; |
||
| 287 | |||
| 288 | case DEULIGNE__DISPLAY_LINE_2: |
||
| 289 | { |
||
| 290 | command |= LCD__CMD_DISPLAY_LINE_2; |
||
| 291 | } |
||
| 292 | break; |
||
| 293 | |||
| 294 | default: |
||
| 295 | break; |
||
| 296 | } |
||
| 297 | |||
| 298 | switch (character_font) |
||
| 299 | { |
||
| 300 | case DEULIGNE__CHARACTER_FONT_5x8_DOTS: |
||
| 301 | { |
||
| 302 | command |= LCD__CMD_CHARACTER_FONT_5x8_DOTS; |
||
| 303 | } |
||
| 304 | break; |
||
| 305 | |||
| 306 | case DEULIGNE__CHARACTER_FONT_5x10_DOTS: |
||
| 307 | { |
||
| 308 | command |= LCD__CMD_CHARACTER_FONT_5x10_DOTS; |
||
| 309 | } |
||
| 310 | break; |
||
| 311 | |||
| 312 | default: |
||
| 313 | break; |
||
| 314 | } |
||
| 315 | |||
| 316 | deuligne__write_command(command); |
||
| 317 | } |
||
| 318 | |||
| 319 | /**************************************************************************//** |
||
| 320 | * \fn void deuligne__set_entry_mode( |
||
| 321 | * deuligne__address_mode_t address_mode, |
||
| 322 | * deuligne__display_shift_t display_shift) |
||
| 323 | * |
||
| 324 | * \brief Set LCD display entry mode. |
||
| 325 | * |
||
| 326 | * \param address_mode specify if DDRAM address is incremented or decremented |
||
| 327 | * when a character code is written |
||
| 328 | * \param display_shift set the display shift when a character code is written |
||
| 329 | ******************************************************************************/ |
||
| 330 | void |
||
| 331 | deuligne__set_entry_mode |
||
| 332 | ( |
||
| 333 | deuligne__address_mode_t address_mode, |
||
| 334 | deuligne__display_shift_t display_shift |
||
| 335 | ){ |
||
| 336 | uint8_t command = LCD__CMD_ENTRY_MODE_SET; |
||
| 337 | |||
| 338 | switch (address_mode) |
||
| 339 | { |
||
| 340 | case DEULIGNE__INCREMENT_ADDRESS: |
||
| 341 | { |
||
| 342 | command |= LCD__CMD_INCREMENT_ADDRESS; |
||
| 343 | } |
||
| 344 | break; |
||
| 345 | |||
| 346 | case DEULIGNE__DECREMENT_ADDRESS: |
||
| 347 | { |
||
| 348 | command |= LCD__CMD_DECREMENT_ADDRESS; |
||
| 349 | } |
||
| 350 | break; |
||
| 351 | |||
| 352 | default: |
||
| 353 | break; |
||
| 354 | } |
||
| 355 | |||
| 356 | switch (display_shift) |
||
| 357 | { |
||
| 358 | case DEULIGNE__DISPLAY_SHIFT_DISABLED: |
||
| 359 | { |
||
| 360 | command |= LCD__CMD_DISPLAY_SHIFT_DISABLED; |
||
| 361 | } |
||
| 362 | break; |
||
| 363 | |||
| 364 | case DEULIGNE__DISPLAY_SHIFT_RIGHT: |
||
| 365 | { |
||
| 366 | command |= LCD__CMD_DISPLAY_SHIFT_RIGHT; |
||
| 367 | } |
||
| 368 | break; |
||
| 369 | |||
| 370 | case DEULIGNE__DISPLAY_SHIFT_LEFT: |
||
| 371 | { |
||
| 372 | command |= LCD__CMD_DISPLAY_SHIFT_LEFT; |
||
| 373 | } |
||
| 374 | break; |
||
| 375 | |||
| 376 | default: |
||
| 377 | break; |
||
| 378 | } |
||
| 379 | |||
| 380 | deuligne__write_command(command); |
||
| 381 | } |
||
| 382 | |||
| 383 | /**************************************************************************//** |
||
| 384 | * \fn void deuligne__set_display( |
||
| 385 | * bool enable_display, |
||
| 386 | * bool enable_cursor_display, |
||
| 387 | * bool enable_cursor_blink) |
||
| 388 | * |
||
| 389 | * \brief Set LCD display. |
||
| 390 | * Enable or disable display, cursor display and cursor blink. |
||
| 391 | * |
||
| 392 | * \param enable_display true to enable display or false in contrary case |
||
| 393 | * \param enable_cursor_display true to enable cursor display or false in |
||
| 394 | * contrary case |
||
| 395 | * \param enable_cursor_blink true to enable cursor blink or false in contrary |
||
| 396 | * case |
||
| 397 | ******************************************************************************/ |
||
| 398 | void |
||
| 399 | deuligne__set_display |
||
| 400 | ( |
||
| 401 | bool enable_display, |
||
| 402 | bool enable_cursor_display, |
||
| 403 | bool enable_cursor_blink |
||
| 404 | ){ |
||
| 405 | uint8_t command = LCD__CMD_DISPLAY_CONTROL; |
||
| 406 | if (enable_display) |
||
| 407 | { |
||
| 408 | command |= LCD__CMD_ENABLE_DISPLAY; |
||
| 409 | } |
||
| 410 | if (enable_cursor_display) |
||
| 411 | { |
||
| 412 | command |= LCD__CMD_ENABLE_CURSOR_DISPLAY; |
||
| 413 | } |
||
| 414 | if (enable_cursor_blink) |
||
| 415 | { |
||
| 416 | command |= LCD__CMD_ENABLE_CURSOR_BLINK; |
||
| 417 | } |
||
| 418 | deuligne__write_command(command); |
||
| 419 | } |
||
| 420 | |||
| 421 | /**************************************************************************//** |
||
| 422 | * \fn void deuligne__clear_display(void) |
||
| 423 | * |
||
| 424 | * \brief Clear LCD display. |
||
| 425 | * Wait time of 2 ms. |
||
| 426 | ******************************************************************************/ |
||
| 427 | void |
||
| 428 | deuligne__clear_display |
||
| 429 | ( |
||
| 430 | void |
||
| 431 | ){ |
||
| 432 | deuligne__write_command(LCD__CMD_CLEAR_DISPLAY); |
||
| 433 | _delay_ms(2); |
||
| 434 | } |
||
| 435 | |||
| 436 | /**************************************************************************//** |
||
| 437 | * \fn void deuligne__return_home(void) |
||
| 438 | * |
||
| 439 | * \brief Set cursor on the first column of the first line. |
||
| 440 | * Wait time of 2 ms. |
||
| 441 | ******************************************************************************/ |
||
| 442 | void |
||
| 443 | deuligne__return_home |
||
| 444 | ( |
||
| 445 | void |
||
| 446 | ){ |
||
| 447 | deuligne__write_command(LCD__CMD_RETURN_HOME); |
||
| 448 | _delay_ms(2); |
||
| 449 | } |
||
| 450 | |||
| 451 | /**************************************************************************//** |
||
| 452 | *\fn void deuligne__set_cursor_position( |
||
| 453 | * deuligne__line_t line, |
||
| 454 | * uint8_t column) |
||
| 455 | * |
||
| 456 | * \brief Set cursor position. |
||
| 457 | * |
||
| 458 | * \param line destination line |
||
| 459 | * \param column destination column |
||
| 460 | ******************************************************************************/ |
||
| 461 | void |
||
| 462 | deuligne__set_cursor_position |
||
| 463 | ( |
||
| 464 | deuligne__line_t line, |
||
| 465 | uint8_t column |
||
| 466 | ){ |
||
| 467 | uint8_t address = 0; |
||
| 468 | |||
| 469 | switch (line) |
||
| 470 | { |
||
| 471 | case DEULIGNE__LINE_1: |
||
| 472 | { |
||
| 473 | address = LCD__LINE_1_ADDRESS; |
||
| 474 | } |
||
| 475 | break; |
||
| 476 | |||
| 477 | case DEULIGNE__LINE_2: |
||
| 478 | { |
||
| 479 | address = LCD__LINE_2_ADDRESS; |
||
| 480 | } |
||
| 481 | break; |
||
| 482 | |||
| 483 | case DEULIGNE__LINE_3: |
||
| 484 | { |
||
| 485 | address = LCD__LINE_3_ADDRESS; |
||
| 486 | } |
||
| 487 | break; |
||
| 488 | |||
| 489 | case DEULIGNE__LINE_4: |
||
| 490 | { |
||
| 491 | address = LCD__LINE_4_ADDRESS; |
||
| 492 | } |
||
| 493 | break; |
||
| 494 | |||
| 495 | default: |
||
| 496 | { |
||
| 497 | address = LCD__LINE_1_ADDRESS; |
||
| 498 | } |
||
| 499 | break; |
||
| 500 | } |
||
| 501 | |||
| 502 | address += column; |
||
| 503 | |||
| 504 | deuligne__write_command(LCD__CMD_SET_CGRAM_ADDRESS + address); |
||
| 505 | } |
||
| 506 | |||
| 507 | /**************************************************************************//** |
||
| 508 | * \fn void deuligne__shift_display(deuligne__shift_direction_t shift_direction) |
||
| 509 | * |
||
| 510 | * \brief Shift the display on the right or on the left. |
||
| 511 | * |
||
| 512 | * \param shift_direction display shift direction |
||
| 513 | ******************************************************************************/ |
||
| 514 | void |
||
| 515 | deuligne__shift_display |
||
| 516 | ( |
||
| 517 | deuligne__shift_direction_t shift_direction |
||
| 518 | ){ |
||
| 519 | uint8_t command = LCD__CMD_CURSOR_OR_DISPLAY_SHIFT | LCD__CMD_SHIFT_DISPLAY; |
||
| 520 | |||
| 521 | switch (shift_direction) |
||
| 522 | { |
||
| 523 | case DEULIGNE__SHIFT_DIRECTION_RIGHT: |
||
| 524 | { |
||
| 525 | command |= LCD__CMD_SHIFT_RIGHT; |
||
| 526 | } |
||
| 527 | break; |
||
| 528 | |||
| 529 | case DEULIGNE__SHIFT_DIRECTION_LEFT: |
||
| 530 | { |
||
| 531 | command |= LCD__CMD_SHIFT_LEFT; |
||
| 532 | } |
||
| 533 | break; |
||
| 534 | |||
| 535 | default: |
||
| 536 | break; |
||
| 537 | } |
||
| 538 | |||
| 539 | deuligne__write_command(command); |
||
| 540 | } |
||
| 541 | |||
| 542 | /**************************************************************************//** |
||
| 543 | * \fn void deuligne__shift_cursor(deuligne__shift_direction_t shift_direction) |
||
| 544 | * |
||
| 545 | * \brief Shift the cursor on the right or on the left. |
||
| 546 | * |
||
| 547 | * \param shift_direction cursor shift direction |
||
| 548 | ******************************************************************************/ |
||
| 549 | void |
||
| 550 | deuligne__shift_cursor |
||
| 551 | ( |
||
| 552 | deuligne__shift_direction_t shift_direction |
||
| 553 | ){ |
||
| 554 | uint8_t command = LCD__CMD_CURSOR_OR_DISPLAY_SHIFT | LCD__CMD_SHIFT_CURSOR; |
||
| 555 | |||
| 556 | switch (shift_direction) |
||
| 557 | { |
||
| 558 | case DEULIGNE__SHIFT_DIRECTION_RIGHT: |
||
| 559 | { |
||
| 560 | command |= LCD__CMD_SHIFT_RIGHT; |
||
| 561 | } |
||
| 562 | break; |
||
| 563 | |||
| 564 | case DEULIGNE__SHIFT_DIRECTION_LEFT: |
||
| 565 | { |
||
| 566 | command |= LCD__CMD_SHIFT_LEFT; |
||
| 567 | } |
||
| 568 | break; |
||
| 569 | |||
| 570 | default: |
||
| 571 | break; |
||
| 572 | } |
||
| 573 | |||
| 574 | deuligne__write_command(command); |
||
| 575 | } |
||
| 576 | |||
| 577 | /**************************************************************************//** |
||
| 578 | * \fn void deuligne__write_char(char data) |
||
| 579 | * |
||
| 580 | * \brief Write a character on LCD. |
||
| 581 | * |
||
| 582 | * \param data Character to write. |
||
| 583 | ******************************************************************************/ |
||
| 584 | void |
||
| 585 | deuligne__write_char |
||
| 586 | ( |
||
| 587 | char data |
||
| 588 | ){ |
||
| 589 | mcp23008__set_pin_level(DEULIGNE__GPIO_RS, MCP23008__LEVEL__HIGH); |
||
| 590 | deuligne__write_byte(data); |
||
| 591 | } |
||
| 592 | |||
| 593 | /**************************************************************************//** |
||
| 594 | * \fn void deuligne__write_string(const char* string_to_write) |
||
| 595 | * |
||
| 596 | * \brief Write a string on LCD display from current cursor position. |
||
| 597 | * |
||
| 598 | * \param string_to_write string to write |
||
| 599 | ******************************************************************************/ |
||
| 600 | void |
||
| 601 | deuligne__write_string |
||
| 602 | ( |
||
| 603 | const char* string_to_write |
||
| 604 | ){ |
||
| 605 | // Check the preconditions. |
||
| 606 | assert(NULL != string_to_write); |
||
| 607 | |||
| 608 | while (*string_to_write != '\0') |
||
| 609 | { |
||
| 610 | deuligne__write_char(*string_to_write++); |
||
| 611 | } |
||
| 612 | } |
||
| 613 | |||
| 614 | /**************************************************************************//** |
||
| 615 | * \fn void deuligne__get_key(void) |
||
| 616 | * |
||
| 617 | * \brief Get key. |
||
| 618 | * |
||
| 619 | * \return Key. |
||
| 620 | ******************************************************************************/ |
||
| 621 | deuligne__key_t |
||
| 622 | deuligne__get_key |
||
| 623 | ( |
||
| 624 | void |
||
| 625 | ){ |
||
| 626 | deuligne__key_t key = DEULIGNE__KEY__NONE; |
||
| 627 | |||
| 628 | // Read ADC0 value. |
||
| 629 | uint16_t value = adc__single_channel_read(); |
||
| 630 | |||
| 631 | // Find key. |
||
| 632 | for (deuligne__key_t i = DEULIGNE__KEY__RIGHT; i <= DEULIGNE__KEY__NONE; i++) |
||
| 633 | { |
||
| 634 | if (value < deuligne__adc_values[i]) |
||
| 635 | { |
||
| 636 | key = i; |
||
| 637 | break; |
||
| 638 | } |
||
| 639 | } |
||
| 640 | |||
| 641 | return key; |
||
| 642 | } |
||
| 643 | |||
| 644 | /****************************************************************************** |
||
| 645 | * Private function definitions. |
||
| 646 | ******************************************************************************/ |
||
| 647 | |||
| 648 | /**************************************************************************//** |
||
| 649 | * \fn static void deuligne__write_command(uint8_t command) |
||
| 650 | * |
||
| 651 | * \brief Write a command on LCD port. |
||
| 652 | * |
||
| 653 | * \param command Command to write. |
||
| 654 | ******************************************************************************/ |
||
| 655 | static |
||
| 656 | void |
||
| 657 | deuligne__write_command |
||
| 658 | ( |
||
| 659 | uint8_t command |
||
| 660 | ){ |
||
| 661 | mcp23008__set_pin_level(DEULIGNE__GPIO_RS, MCP23008__LEVEL__LOW); |
||
| 662 | deuligne__write_byte(command); |
||
| 663 | } |
||
| 664 | |||
| 665 | /**************************************************************************//** |
||
| 666 | * \fn static void deuligne__write_byte(uint8_t data) |
||
| 667 | * |
||
| 668 | * \brief Write a byte on LCD port. |
||
| 669 | * |
||
| 670 | * \param data Byte to write. |
||
| 671 | ******************************************************************************/ |
||
| 672 | static |
||
| 673 | void |
||
| 674 | deuligne__write_byte |
||
| 675 | ( |
||
| 676 | uint8_t data |
||
| 677 | ){ |
||
| 678 | // Get current port value. |
||
| 679 | uint8_t port_value = mcp23008__get_port_value() & 0xF0; |
||
| 680 | |||
| 681 | // Write high nibble. |
||
| 682 | port_value |= data >> 4; |
||
| 683 | mcp23008__set_port_value(port_value); |
||
| 684 | deuligne__enable_data(); |
||
| 685 | _delay_ms(1); |
||
| 686 | |||
| 687 | // Write low nibble. |
||
| 688 | port_value &= 0xF0; |
||
| 689 | port_value |= data & 0x0F; |
||
| 690 | mcp23008__set_port_value(port_value); |
||
| 691 | deuligne__enable_data(); |
||
| 692 | _delay_ms(1); |
||
| 693 | } |
||
| 694 | |||
| 695 | /**************************************************************************//** |
||
| 696 | * \fn static void deuligne__write_high_nibble(uint8_t data) |
||
| 697 | * |
||
| 698 | * \brief Write the high nibble of a byte on LCD port. |
||
| 699 | * |
||
| 700 | * \param data Byte which write high nibble. |
||
| 701 | ******************************************************************************/ |
||
| 702 | static |
||
| 703 | void |
||
| 704 | deuligne__write_high_nibble |
||
| 705 | ( |
||
| 706 | uint8_t data |
||
| 707 | ){ |
||
| 708 | // Get current port value. |
||
| 709 | uint8_t port_value = mcp23008__get_port_value() & 0xF0; |
||
| 710 | |||
| 711 | // Write high nibble. |
||
| 712 | port_value |= data >> 4; |
||
| 713 | mcp23008__set_port_value(port_value); |
||
| 714 | deuligne__enable_data(); |
||
| 715 | _delay_ms(1); |
||
| 716 | } |
||
| 717 | |||
| 718 | /**************************************************************************//** |
||
| 719 | * \fn static void deuligne__enable_data(void) |
||
| 720 | * |
||
| 721 | * \brief Enable data on LCD port. |
||
| 722 | ******************************************************************************/ |
||
| 723 | static |
||
| 724 | void |
||
| 725 | deuligne__enable_data |
||
| 726 | ( |
||
| 727 | void |
||
| 728 | ){ |
||
| 729 | mcp23008__set_pin_level(DEULIGNE__GPIO_E, MCP23008__LEVEL__HIGH); |
||
| 730 | _delay_ms(1); |
||
| 731 | mcp23008__set_pin_level(DEULIGNE__GPIO_E, MCP23008__LEVEL__LOW); |
||
| 732 | _delay_ms(1); |
||
| 733 | } |