diff options
Diffstat (limited to 'bsps/shared/dev/display/disp_hcms29xx.c')
-rw-r--r-- | bsps/shared/dev/display/disp_hcms29xx.c | 932 |
1 files changed, 932 insertions, 0 deletions
diff --git a/bsps/shared/dev/display/disp_hcms29xx.c b/bsps/shared/dev/display/disp_hcms29xx.c new file mode 100644 index 0000000000..5730b36ea9 --- /dev/null +++ b/bsps/shared/dev/display/disp_hcms29xx.c @@ -0,0 +1,932 @@ +/*===============================================================*\ +| Project: display driver for HCMS29xx | ++-----------------------------------------------------------------+ +| File: disp_hcms29xx.c | ++-----------------------------------------------------------------+ +| Copyright (c) 2008 | +| Embedded Brains GmbH | +| Obere Lagerstr. 30 | +| D-82178 Puchheim | +| Germany | +| rtems@embedded-brains.de | ++-----------------------------------------------------------------+ +| The license and distribution terms for this file may be | +| found in the file LICENSE in this distribution or at | +| http://www.rtems.org/license/LICENSE. | ++-----------------------------------------------------------------+ +| this file contains the SPI based driver for a HCMS29xx 4 digit | +| alphanumeric LED display | +\*===============================================================*/ + +#include <string.h> +#include <stdlib.h> + +#include <rtems.h> +#include <rtems/libio.h> +#include <bsp.h> +#include <rtems/libi2c.h> +#include <libchip/disp_hcms29xx.h> +#include "font_hcms29xx.h" +#define FONT_BASE font_hcms29xx_base + + +#define DISP_HCMS29XX_DIGIT_CNT (4) +#define DISP_HCMS29XX_SEMA_NAME rtems_build_name('D','4','I','Q') +#define DISP_HCMS29XX_TRNS_SEMA_NAME rtems_build_name('D','4','T','R') +#define DISP_HCMS29XX_TIMER_NAME rtems_build_name('D','4','T','M') +#define DISP_HCMS29XX_TASK_NAME rtems_build_name('D','4','T','A') + +#define DISP_HCMS29XX_EVENT_TIMER RTEMS_EVENT_1 +#define DISP_HCMS29XX_EVENT_NEWSTR RTEMS_EVENT_2 + + +static disp_font_t disp_hcms29xx_font_normal; +static disp_font_t disp_hcms29xx_font_rotate; +const rtems_libi2c_tfr_mode_t spi_disphcms29xx_tfr_mode = { + .baudrate = 1000000, + .bits_per_char = 8, + .lsb_first = true, + .clock_inv = true, + .clock_phs = true, + .idle_char = 0 +}; + +static disp_hcms29xx_drv_t disp_hcms29xx_drv_tbl; + +/*========================================= + * font management functions + */ + +/*=========================================================================*\ +| Function: | +\*-------------------------------------------------------------------------*/ +static rtems_status_code disp_hcms29xx_font_struct_size + ( +/*-------------------------------------------------------------------------*\ +| Purpose: | +| compute size of font data structure tree | ++---------------------------------------------------------------------------+ +| Input Parameters: | +\*-------------------------------------------------------------------------*/ + disp_font_t src, /* source font */ + size_t *dst_size /* destination: size of font struct*/ +) +/*-------------------------------------------------------------------------*\ +| Return Value: | +| rtems_status_code | +\*=========================================================================*/ +{ + + rtems_status_code rc = RTEMS_SUCCESSFUL; + size_t font_size = 0; + size_t glyph_idx; + /* + * check parameters + */ + if ((rc == RTEMS_SUCCESSFUL) && + (src == NULL)) { + rc = RTEMS_INVALID_ADDRESS; + } + if (rc == RTEMS_SUCCESSFUL) { + font_size = + sizeof(*src); /* font_base structure */ + } + glyph_idx = 0; + while ((rc == RTEMS_SUCCESSFUL) && + (glyph_idx < (sizeof(src->latin1)/sizeof(src->latin1[0])))) { + if (src->latin1[glyph_idx] != NULL) { + font_size += sizeof(*(src->latin1[glyph_idx])) + + (size_t) src->latin1[glyph_idx]->bb.w; + } + glyph_idx++; + } + *dst_size = font_size; + + return rc; +} + +/*=========================================================================*\ +| Function: | +\*-------------------------------------------------------------------------*/ +static inline unsigned char disp_hcms29xx_bitswap + ( +/*-------------------------------------------------------------------------*\ +| Purpose: | +| swap data bits in byte (7<->0 , 6<->1 etc) | ++---------------------------------------------------------------------------+ +| Input Parameters: | +\*-------------------------------------------------------------------------*/ + unsigned char byte +) +/*-------------------------------------------------------------------------*\ +| Return Value: | +| rtems_status_code | +\*=========================================================================*/ +{ + unsigned char result = 0; + int smsk,dmsk; + for (smsk = 0x01,dmsk=0x80; + smsk < 0x100; + smsk<<=1 ,dmsk>>=1) { + if ((byte & smsk) != 0) { + result |= (unsigned char) dmsk; + } + } + return result; +} + +/*=========================================================================*\ +| Function: | +\*-------------------------------------------------------------------------*/ +static rtems_status_code disp_hcms29xx_copy_font + ( +/*-------------------------------------------------------------------------*\ +| Purpose: | +| copy font data from source to dest font structure | ++---------------------------------------------------------------------------+ +| Input Parameters: | +\*-------------------------------------------------------------------------*/ + disp_font_t src, /* source font */ + struct disp_font_base *dst, /* ptr to destination font */ + int shift_cnt, /* shift count for font */ + bool do_rotate /* rotate font, if true */ +) +/*-------------------------------------------------------------------------*\ +| Return Value: | +| rtems_status_code | +\*=========================================================================*/ +{ + + rtems_status_code rc = RTEMS_SUCCESSFUL; + char *alloc_next = (char *)dst; + size_t glyph_idx = 0; + int glyph_size; + unsigned char byte; + int bcnt; + + /* + * check parameters + */ + if ((rc == RTEMS_SUCCESSFUL) && + ((src == NULL) || + (dst == NULL))) { + rc = RTEMS_INVALID_ADDRESS; + } + /* + * copy font_base structure + */ + if (rc == RTEMS_SUCCESSFUL) { + *dst = *src; + alloc_next += sizeof(*dst); + } + /* + * for all glyphs: assign own glyph memory + */ + glyph_idx = 0; + while ((rc == RTEMS_SUCCESSFUL) && + glyph_idx < (sizeof(src->latin1)/sizeof(src->latin1[0]))) { + if (src->latin1[glyph_idx] != NULL) { + /* + * allocate space for glyph + */ + dst->latin1[glyph_idx] = (struct disp_font_glyph *)alloc_next; + alloc_next += sizeof(*(dst->latin1[glyph_idx])); + /* + * copy source values. + * Note: bitmap will be reassigned later + */ + *(struct disp_font_glyph *)(dst->latin1[glyph_idx]) = + *(src->latin1[glyph_idx]); + } + else { + dst->latin1[glyph_idx] = NULL; + } + glyph_idx++; + } + + /* + * for all glyphs: reassign bitmap + */ + glyph_idx = 0; + while ((rc == RTEMS_SUCCESSFUL) && + glyph_idx < (sizeof(src->latin1)/sizeof(src->latin1[0]))) { + if (src->latin1[glyph_idx] != NULL) { + glyph_size = src->latin1[glyph_idx]->bb.w; + /* + * allocate space for glyph_bitmap + */ + dst->latin1[glyph_idx]->bitmap = (const unsigned char *) alloc_next; + alloc_next += glyph_size; + /* + * copy/transform bitmap + */ + for (bcnt = 0;bcnt < glyph_size;bcnt++) { + if (do_rotate) { + byte = src->latin1[glyph_idx]->bitmap[glyph_size - 1 - bcnt]; + byte = disp_hcms29xx_bitswap(byte); + } + else { + byte = src->latin1[glyph_idx]->bitmap[bcnt]; + } + if (shift_cnt < 0) { + byte = byte >> shift_cnt; + } + else if (shift_cnt > 0) { + byte = byte >> shift_cnt; + } + ((unsigned char *)(dst->latin1[glyph_idx]->bitmap))[bcnt] = byte; + } + } + glyph_idx++; + } + return rc; +} + +/*=========================================================================*\ +| Function: | +\*-------------------------------------------------------------------------*/ +static rtems_status_code disp_hcms29xx_alloc_copy_font + ( +/*-------------------------------------------------------------------------*\ +| Purpose: | +| copy font data from source to dest font structure, alloc all data | ++---------------------------------------------------------------------------+ +| Input Parameters: | +\*-------------------------------------------------------------------------*/ + const disp_font_t src, /* source font */ + disp_font_t *dst, /* ptr to destination font */ + int shift_cnt, /* shift count for font */ + bool do_rotate /* rotate font, if true */ +) +/*-------------------------------------------------------------------------*\ +| Return Value: | +| rtems_status_code | +\*=========================================================================*/ +{ + + rtems_status_code rc = RTEMS_SUCCESSFUL; + size_t src_size = 0; + /* + * check parameters + */ + if ((rc == RTEMS_SUCCESSFUL) && + ((src == NULL) + || (dst == NULL))) { + rc = RTEMS_INVALID_ADDRESS; + } + /* + * determine size of source data + */ + if (rc == RTEMS_SUCCESSFUL) { + rc = disp_hcms29xx_font_struct_size(src,&src_size); + } + /* + * allocate proper data area + */ + if (rc == RTEMS_SUCCESSFUL) { + *dst = malloc(src_size); + if (*dst == NULL) { + rc = RTEMS_UNSATISFIED; + } + } + /* + * scan through source data, copy to dest + */ + if (rc == RTEMS_SUCCESSFUL) { + rc = disp_hcms29xx_copy_font(src,*dst,shift_cnt,do_rotate); + } + return rc; +} + +/*========================================= + * SPI communication functions + */ + +/*=========================================================================*\ +| Function: | +\*-------------------------------------------------------------------------*/ +static rtems_status_code disp_hcms29xx_send_to_display + ( +/*-------------------------------------------------------------------------*\ +| Purpose: | +| request access semaphore to SPI, prepare buffer descriptors, start | +| transfer via SPI to display | ++---------------------------------------------------------------------------+ +| Input Parameters: | +\*-------------------------------------------------------------------------*/ + disp_hcms29xx_drv_t *softc_ptr, + const volatile char *disp_buffer /* start of chars to display (4 chars or 'til \0)*/ +) +/*-------------------------------------------------------------------------*\ +| Return Value: | +| rtems_status_code | +\*=========================================================================*/ +{ + rtems_status_code rc = RTEMS_SUCCESSFUL; + bool char_avail; + const struct disp_font_glyph *glyph_ptr; + disp_font_t curr_font; + int i, ret_cnt; + unsigned char c; + + /* + * select device, set transfer mode, address device + */ + if (rc == RTEMS_SUCCESSFUL) { + rc = rtems_libi2c_send_start(softc_ptr->disp_param.minor); + } + /* + * set transfer mode + */ + if (rc == RTEMS_SUCCESSFUL) { + rc = -rtems_libi2c_ioctl(softc_ptr->disp_param.minor, + RTEMS_LIBI2C_IOCTL_SET_TFRMODE, + &spi_disphcms29xx_tfr_mode); + } + + /* + * address device + */ + if (rc == RTEMS_SUCCESSFUL) { + rc = rtems_libi2c_send_addr(softc_ptr->disp_param.minor,true); + } + + /* + * send data + */ + if (rc == RTEMS_SUCCESSFUL) { + curr_font = + softc_ptr->disp_param.rotate + ? disp_hcms29xx_font_rotate + : disp_hcms29xx_font_normal; + + char_avail = true; + /* + * FIXME: for rotated display, write last character first... + * maybe we should copy everything to a common buffer and use + * ONE SPI transfer? + */ + for (i = 0; + ((rc == RTEMS_SUCCESSFUL) && + (i < DISP_HCMS29XX_DIGIT_CNT)); + i++) { + /* test for end of string... */ + c = disp_buffer[i]; /* perform consistent read of disp_buffer */ + if (char_avail && (c == '\0')) { + char_avail = false; + } + glyph_ptr = (char_avail + ? curr_font->latin1[c] + : NULL); + if (glyph_ptr == NULL) { + glyph_ptr = curr_font->latin1[' ']; + } + + /* + * send 5 bytes from (char *)glyph_ptr->bitmap to SPI + */ + if (rc == RTEMS_SUCCESSFUL) { + ret_cnt = rtems_libi2c_write_bytes(softc_ptr->disp_param.minor, + glyph_ptr->bitmap,5); + if (ret_cnt < 0) { + rc = -ret_cnt; + } + } + } + } + /* + * finish transfer + */ + if (rc == RTEMS_SUCCESSFUL) { + rc = rtems_libi2c_send_stop(softc_ptr->disp_param.minor); + } + + return rc; +} + +/*=========================================================================*\ +| Function: | +\*-------------------------------------------------------------------------*/ +static rtems_status_code disp_hcms29xx_send_to_control + ( +/*-------------------------------------------------------------------------*\ +| Purpose: | +| request access semaphore to SPI, prepare buffer descriptors, start | +| transfer via SPI to display | ++---------------------------------------------------------------------------+ +| Input Parameters: | +\*-------------------------------------------------------------------------*/ + disp_hcms29xx_drv_t *softc_ptr, + int pwm, /* value for pwm of LEDs, 0..15 */ + int peak, /* value for peak current for LEDs, 0..3 */ + int sleep, /* value to make display "sleep" (0..1 */ + int div, /* divider for external osc input, unused here */ + int chain /* mode to drive other displays, unused here */ +) +/*-------------------------------------------------------------------------*\ +| Return Value: | +| rtems_status_code | +\*=========================================================================*/ +{ + rtems_status_code rc = RTEMS_SUCCESSFUL; + int run, ret_cnt; + uint8_t ctrl_buffer; + + /* two accesses, control word 0 and 1 */ + for (run = 0; + ((rc == RTEMS_SUCCESSFUL) && (run <= 1)); + run++) { + if (rc == RTEMS_SUCCESSFUL) { + if (run == 0) { + ctrl_buffer = + (0 << 7) | + ((sleep & 0x01) << 6) | + ((peak & 0x03) << 4) | + ((pwm & 0x0f) << 0); + } + else { + ctrl_buffer = + (1 << 7) | + ((div & 0x01) << 1) | + ((chain & 0x01) << 0); + } + /* + * select device, set transfer mode, address device + */ + if (rc == RTEMS_SUCCESSFUL) { + rc = rtems_libi2c_send_start(softc_ptr->disp_param.minor); + } + /* + * set transfer mode + */ + if (rc == RTEMS_SUCCESSFUL) { + rc = -rtems_libi2c_ioctl(softc_ptr->disp_param.minor, + RTEMS_LIBI2C_IOCTL_SET_TFRMODE, + &spi_disphcms29xx_tfr_mode); + } + + /* + * address device + */ + if (rc == RTEMS_SUCCESSFUL) { + rc = rtems_libi2c_send_addr(softc_ptr->disp_param.minor,true); + } + + /* + * send 1 byte from ctrl_buffer + */ + if (rc == RTEMS_SUCCESSFUL) { + ret_cnt = rtems_libi2c_write_bytes(softc_ptr->disp_param.minor, + &ctrl_buffer,1); + if (ret_cnt < 0) { + rc = -ret_cnt; + } + } + } + } /* next run ... */ + + /* + * finish transfer + */ + if (rc == RTEMS_SUCCESSFUL) { + rc = rtems_libi2c_send_stop(softc_ptr->disp_param.minor); + } + + return rc; +} + +/*=========================================================================*\ +| Function: | +\*-------------------------------------------------------------------------*/ +static rtems_timer_service_routine disp_hcms29xx_timer_sr +/*-------------------------------------------------------------------------*\ +| Purpose: | +| this task updates the string in the display | ++---------------------------------------------------------------------------+ +| Input Parameters: | +\*-------------------------------------------------------------------------*/ +( + rtems_id id, /* ID of timer, not used */ + void * arg /* calling arg: softc_ptr */ +) +/*-------------------------------------------------------------------------*\ +| Return Value: | +| <none used> | +\*=========================================================================*/ +{ + disp_hcms29xx_drv_t *softc_ptr = arg; + + rtems_event_send(softc_ptr->disp_param.task_id, DISP_HCMS29XX_EVENT_TIMER); +} + +/*=========================================================================*\ +| Function: | +\*-------------------------------------------------------------------------*/ +static rtems_task disp_hcms29xx_update_task + ( +/*-------------------------------------------------------------------------*\ +| Purpose: | +| this task updates the string in the display | ++---------------------------------------------------------------------------+ +| Input Parameters: | +\*-------------------------------------------------------------------------*/ + rtems_task_argument argument +) +/*-------------------------------------------------------------------------*\ +| Return Value: | +| <never exits> | +\*=========================================================================*/ +{ + rtems_event_set my_events; + rtems_status_code rc = RTEMS_SUCCESSFUL; + int disp_offset = 0; + rtems_id disp_hcms29xx_timer_id; + disp_hcms29xx_drv_t *softc_ptr = &disp_hcms29xx_drv_tbl; + + /* + * initialize display: + */ + /* + * set control attributes for display + * maximum brightness... + */ + if (rc == RTEMS_SUCCESSFUL) { + rc = disp_hcms29xx_send_to_control(softc_ptr, + 14,3,1,0,0);/* pwm/peak/nosleep/div/chain */ + } + + /* + * set display to blank + */ + if (rc == RTEMS_SUCCESSFUL) { + rc = disp_hcms29xx_send_to_display(softc_ptr, + ""); + } + + /* + * create timer for scrolling + */ + if (rc == RTEMS_SUCCESSFUL) { + rc = rtems_timer_create(DISP_HCMS29XX_TIMER_NAME, + &disp_hcms29xx_timer_id); + } + + while (rc == RTEMS_SUCCESSFUL) { + /* + * wait for any event + */ + rc = rtems_event_receive(DISP_HCMS29XX_EVENT_NEWSTR | + DISP_HCMS29XX_EVENT_TIMER , + RTEMS_WAIT | RTEMS_EVENT_ANY, + RTEMS_NO_TIMEOUT, + &my_events); + if (my_events & DISP_HCMS29XX_EVENT_NEWSTR) { + /* + * fetch new string consistently into local buffer + */ + if (rc == RTEMS_SUCCESSFUL) { + rc = rtems_semaphore_obtain(softc_ptr->disp_param.trns_sema_id, + RTEMS_WAIT,RTEMS_NO_TIMEOUT); + } + if (rc == RTEMS_SUCCESSFUL) { + strncpy(softc_ptr->disp_param.disp_buffer, + softc_ptr->disp_param.trns_buffer, + sizeof(softc_ptr->disp_param.disp_buffer)); + softc_ptr->disp_param.disp_buffer[sizeof(softc_ptr->disp_param.disp_buffer)-1] = '\0'; + softc_ptr->disp_param.disp_buf_cnt = + (int) strlen(softc_ptr->disp_param.disp_buffer); + } + if (rc == RTEMS_SUCCESSFUL) { + rc = rtems_semaphore_release(softc_ptr->disp_param.trns_sema_id); + } + /* + * set initial offset to negative value + * to make string static for some ticks + */ + disp_offset = -4; + } + if (my_events & DISP_HCMS29XX_EVENT_TIMER) { + /* + * increase disp_offset, if possible, otherwise reset it + */ + if ((disp_offset < 0) || + (disp_offset < softc_ptr->disp_param.disp_buf_cnt- + DISP_HCMS29XX_DIGIT_CNT/2)) { + disp_offset++; + } + else { + disp_offset = -4; + } + } + /* + * display string, starting from disp_offset + */ + if (disp_offset < 0) { + rc = disp_hcms29xx_send_to_display(softc_ptr, + softc_ptr->disp_param.disp_buffer); + } + else if (disp_offset + < (softc_ptr->disp_param.disp_buf_cnt - DISP_HCMS29XX_DIGIT_CNT)) { + rc = disp_hcms29xx_send_to_display(softc_ptr, + softc_ptr->disp_param.disp_buffer+disp_offset); + } + else { + rc = disp_hcms29xx_send_to_display(softc_ptr, + softc_ptr->disp_param.disp_buffer + + softc_ptr->disp_param.disp_buf_cnt + - DISP_HCMS29XX_DIGIT_CNT); + } + /* + * activate timer, if needed + */ + if (rc == RTEMS_SUCCESSFUL) { + if (softc_ptr->disp_param.disp_buf_cnt > DISP_HCMS29XX_DIGIT_CNT) { + rc = rtems_timer_fire_after(disp_hcms29xx_timer_id, + 50, + disp_hcms29xx_timer_sr, + NULL); + } + else { + rc = rtems_timer_cancel(disp_hcms29xx_timer_id); + } + } + } + /* + * FIXME: display task is dead... + */ +} + +/*=========================================================================*\ +| Function: | +\*-------------------------------------------------------------------------*/ +static rtems_status_code disp_hcms29xx_update + ( +/*-------------------------------------------------------------------------*\ +| Purpose: | +| move given string to display task | ++---------------------------------------------------------------------------+ +| Input Parameters: | +\*-------------------------------------------------------------------------*/ + disp_hcms29xx_drv_t *softc_ptr, + const char *src +) +/*-------------------------------------------------------------------------*\ +| Return Value: | +| rtems_status_code | +\*=========================================================================*/ +{ + rtems_status_code rc = RTEMS_SUCCESSFUL; + + /* + * obtain trns semaphore + */ + if (rc == RTEMS_SUCCESSFUL) { + rc = rtems_semaphore_obtain(softc_ptr->disp_param.trns_sema_id, + RTEMS_WAIT,RTEMS_NO_TIMEOUT); + } + /* + * copy string... + */ + strncpy(softc_ptr->disp_param.trns_buffer,src, + sizeof(softc_ptr->disp_param.trns_buffer)); + softc_ptr->disp_param.trns_buffer[sizeof(softc_ptr->disp_param.trns_buffer)-1] = '\0'; + + /* + * release trns semaphore + */ + if (rc == RTEMS_SUCCESSFUL) { + rc = rtems_semaphore_release(softc_ptr->disp_param.trns_sema_id); + } + + /* + * send event to task + */ + if (rc == RTEMS_SUCCESSFUL) { + rc = rtems_event_send(softc_ptr->disp_param.task_id, + DISP_HCMS29XX_EVENT_NEWSTR); + } + + return rc; +} + +/*=========================================================================*\ +| Function: | +\*-------------------------------------------------------------------------*/ +rtems_device_driver disp_hcms29xx_dev_initialize + ( +/*-------------------------------------------------------------------------*\ +| Purpose: | +| prepare the display device driver to accept write calls | +| register device with its name | ++---------------------------------------------------------------------------+ +| Input Parameters: | +\*-------------------------------------------------------------------------*/ + rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg +) +/*-------------------------------------------------------------------------*\ +| Return Value: | +| rtems_status_code | +\*=========================================================================*/ +/* + * Initialize and register the device + */ +{ + rtems_status_code rc = RTEMS_SUCCESSFUL; + disp_hcms29xx_drv_t *softc_ptr = &disp_hcms29xx_drv_tbl; + + /* + * initialize font management + * FIXME: check, that default glyph exists + * FIXME: check font size to be 5x7 + */ + /* + * translate font according to direction/baseline + */ + if (rc == RTEMS_SUCCESSFUL) { + rc = disp_hcms29xx_alloc_copy_font( + &FONT_BASE, + &disp_hcms29xx_font_normal, + FONT_BASE.descent, /* shift to visibility... */ + FALSE); /* do not rotate */ + } + /* FIXME: translate font for rotation */ + if (rc == RTEMS_SUCCESSFUL) { + rc = disp_hcms29xx_alloc_copy_font(&FONT_BASE, + &disp_hcms29xx_font_rotate, + 0, /* do not shift */ + true); /* rotate font */ + } + /* + * create the trns_buffer semaphore + */ + if (rc == RTEMS_SUCCESSFUL) { + rc = rtems_semaphore_create (DISP_HCMS29XX_TRNS_SEMA_NAME,1, + RTEMS_PRIORITY + |RTEMS_BINARY_SEMAPHORE + |RTEMS_INHERIT_PRIORITY + |RTEMS_NO_PRIORITY_CEILING + |RTEMS_LOCAL, + 0, + &softc_ptr->disp_param.trns_sema_id); + } + + /* + * create and start display task + */ + if (rc == RTEMS_SUCCESSFUL) { + rc = rtems_task_create(DISP_HCMS29XX_TASK_NAME, + 20, + RTEMS_MINIMUM_STACK_SIZE, + RTEMS_INTERRUPT_LEVEL(0) | RTEMS_TIMESLICE, + RTEMS_DEFAULT_ATTRIBUTES, + &softc_ptr->disp_param.task_id); + } + if (rc == RTEMS_SUCCESSFUL) { + rc = rtems_task_start(softc_ptr->disp_param.task_id, + disp_hcms29xx_update_task,0); + } + return rc; +} + +/*=========================================================================*\ +| Function: | +\*-------------------------------------------------------------------------*/ +rtems_device_driver disp_hcms29xx_dev_open +( +/*-------------------------------------------------------------------------*\ +| Purpose: | +| open the display device | ++---------------------------------------------------------------------------+ +| Input Parameters: | +\*-------------------------------------------------------------------------*/ + rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg +) +/*-------------------------------------------------------------------------*\ +| Return Value: | +| rtems_status_code | +\*=========================================================================*/ +{ + disp_hcms29xx_drv_t *softc_ptr = &disp_hcms29xx_drv_tbl; + /* + * ensure, that disp_hcms29xx device is assumed to be empty + */ + softc_ptr->disp_param.dev_buf_cnt = 0; + + return RTEMS_SUCCESSFUL; +} + +/*=========================================================================*\ +| Function: | +\*-------------------------------------------------------------------------*/ +rtems_device_driver disp_hcms29xx_dev_write +( +/*-------------------------------------------------------------------------*\ +| Purpose: | +| write to display device | ++---------------------------------------------------------------------------+ +| Input Parameters: | +\*-------------------------------------------------------------------------*/ + rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg +) +/*-------------------------------------------------------------------------*\ +| Return Value: | +| rtems_status_code | +\*=========================================================================*/ +{ + rtems_libio_rw_args_t *args = arg; + uint32_t cnt; + disp_hcms29xx_drv_t *softc_ptr = &disp_hcms29xx_drv_tbl; + + for (cnt = 0;cnt < args->count;cnt++) { + /* + * accumulate characters written into display dev buffer + */ + if (((softc_ptr->disp_param.dev_buf_cnt > 0) + &&((args->buffer[cnt] == '\n') + || (args->buffer[cnt] == '\0')) + ) + ||( softc_ptr->disp_param.dev_buf_cnt >= + (int) sizeof(softc_ptr->disp_param.dev_buffer) - 1)) { + softc_ptr->disp_param.dev_buffer[softc_ptr->disp_param.dev_buf_cnt] = '\0'; + /* + * transfer string to display string, redisplay it... + */ + disp_hcms29xx_update(softc_ptr,softc_ptr->disp_param.dev_buffer); + softc_ptr->disp_param.dev_buf_cnt = 0; + } + /* + * write to dev_buf, if '\n' occured or display device buffer is full + */ + if ((args->buffer[cnt] != '\n') && + (args->buffer[cnt] != '\0')) { + softc_ptr->disp_param.dev_buffer[softc_ptr->disp_param.dev_buf_cnt++] = + args->buffer[cnt]; + } + } + args->bytes_moved = args->count; + + return RTEMS_SUCCESSFUL; +} + +/*=========================================================================*\ +| Function: | +\*-------------------------------------------------------------------------*/ +rtems_device_driver disp_hcms29xx_dev_close +( +/*-------------------------------------------------------------------------*\ +| Purpose: | +| close the display device | ++---------------------------------------------------------------------------+ +| Input Parameters: | +\*-------------------------------------------------------------------------*/ + rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg +) +/*-------------------------------------------------------------------------*\ +| Return Value: | +| rtems_status_code | +\*=========================================================================*/ +{ + + return RTEMS_SUCCESSFUL; +} + +/* + * driver operation tables + */ +static rtems_driver_address_table disp_hcms29xx_ops = { + .initialization_entry = disp_hcms29xx_dev_initialize, + .open_entry = disp_hcms29xx_dev_open, + .write_entry = disp_hcms29xx_dev_write, + .close_entry = disp_hcms29xx_dev_close +}; + + +static disp_hcms29xx_drv_t disp_hcms29xx_drv_tbl = { + {/* public fields */ + .ops = &disp_hcms29xx_ops, + .size = sizeof (disp_hcms29xx_drv_t), + }, + { /* our private fields */ + 0, + { 0 }, + 0, + { 0 }, + { 0 }, + 0, + 0, + 0, + false + } +}; + +rtems_libi2c_drv_t *disp_hcms29xx_driver_descriptor = + &disp_hcms29xx_drv_tbl.libi2c_drv_entry; + |