source: rtems/c/src/libchip/display/disp_hcms29xx.c @ 64d6f19

4.115
Last change on this file since 64d6f19 was 64d6f19, checked in by Ralf Corsépius <ralf.corsepius@…>, on 10/18/12 at 13:24:39

Eliminate unused var 'digit'.

  • Property mode set to 100644
File size: 32.4 KB
Line 
1/*===============================================================*\
2| Project: display driver for HCMS29xx                            |
3+-----------------------------------------------------------------+
4| File: disp_hcms29xx.c                                           |
5+-----------------------------------------------------------------+
6|                    Copyright (c) 2008                           |
7|                    Embedded Brains GmbH                         |
8|                    Obere Lagerstr. 30                           |
9|                    D-82178 Puchheim                             |
10|                    Germany                                      |
11|                    rtems@embedded-brains.de                     |
12+-----------------------------------------------------------------+
13| The license and distribution terms for this file may be         |
14| found in the file LICENSE in this distribution or at            |
15| http://www.rtems.com/license/LICENSE.                           |
16+-----------------------------------------------------------------+
17| this file contains the SPI based driver for a HCMS29xx 4 digit  |
18| alphanumeric LED display                                        |
19\*===============================================================*/
20
21#include <string.h>
22#include <stdlib.h>
23
24#include <rtems.h>
25#include <rtems/libio.h>
26#include <bsp.h>
27#include <rtems/libi2c.h>
28#include <libchip/disp_hcms29xx.h>
29#include "font_hcms29xx.h"
30#define FONT_BASE font_hcms29xx_base
31
32
33#define DISP_HCMS29XX_DIGIT_CNT (4)
34#define DISP_HCMS29XX_SEMA_NAME      rtems_build_name('D','4','I','Q')
35#define DISP_HCMS29XX_TRNS_SEMA_NAME rtems_build_name('D','4','T','R')
36#define DISP_HCMS29XX_TIMER_NAME     rtems_build_name('D','4','T','M')
37#define DISP_HCMS29XX_TASK_NAME      rtems_build_name('D','4','T','A')
38
39#define DISP_HCMS29XX_EVENT_TIMER  RTEMS_EVENT_1
40#define DISP_HCMS29XX_EVENT_NEWSTR RTEMS_EVENT_2
41
42
43static disp_font_t disp_hcms29xx_font_normal;
44static disp_font_t disp_hcms29xx_font_rotate;
45const rtems_libi2c_tfr_mode_t spi_disphcms29xx_tfr_mode = {
46  .baudrate = 1000000,
47  .bits_per_char = 8,
48  .lsb_first = true,
49  .clock_inv = true,
50  .clock_phs = true,
51  .idle_char = 0
52};
53
54static disp_hcms29xx_drv_t disp_hcms29xx_drv_tbl;
55
56/*=========================================
57 * font management functions
58 */
59
60/*=========================================================================*\
61| Function:                                                                 |
62\*-------------------------------------------------------------------------*/
63static rtems_status_code disp_hcms29xx_font_struct_size
64  (
65/*-------------------------------------------------------------------------*\
66| Purpose:                                                                  |
67|   compute size of font data structure tree                                |
68+---------------------------------------------------------------------------+
69| Input Parameters:                                                         |
70\*-------------------------------------------------------------------------*/
71  disp_font_t            src,           /* source font                     */
72  size_t                *dst_size       /* destination: size of font struct*/
73)
74/*-------------------------------------------------------------------------*\
75| Return Value:                                                             |
76|    rtems_status_code                                                      |
77\*=========================================================================*/
78{
79
80  rtems_status_code rc = RTEMS_SUCCESSFUL;
81  size_t font_size = 0;
82  size_t glyph_idx;
83  /*
84   * check parameters
85   */
86  if ((rc == RTEMS_SUCCESSFUL) &&
87      (src == NULL)) {
88    rc = RTEMS_INVALID_ADDRESS;
89  }
90  if (rc == RTEMS_SUCCESSFUL) {
91    font_size =
92      sizeof(*src);                      /* font_base structure       */
93  }
94  glyph_idx = 0;
95  while ((rc == RTEMS_SUCCESSFUL) &&
96         (glyph_idx < (sizeof(src->latin1)/sizeof(src->latin1[0])))) {
97    if (src->latin1[glyph_idx] != NULL) {
98      font_size += sizeof(*(src->latin1[glyph_idx]))
99        + (size_t) src->latin1[glyph_idx]->bb.w;
100    }
101    glyph_idx++;
102  }
103  *dst_size = font_size;
104
105  return rc;
106}
107
108/*=========================================================================*\
109| Function:                                                                 |
110\*-------------------------------------------------------------------------*/
111static inline unsigned char disp_hcms29xx_bitswap
112  (
113/*-------------------------------------------------------------------------*\
114| Purpose:                                                                  |
115|   swap data bits in byte (7<->0 , 6<->1 etc)                              |
116+---------------------------------------------------------------------------+
117| Input Parameters:                                                         |
118\*-------------------------------------------------------------------------*/
119  unsigned char byte
120)
121/*-------------------------------------------------------------------------*\
122| Return Value:                                                             |
123|    rtems_status_code                                                      |
124\*=========================================================================*/
125{
126  unsigned char result = 0;
127  int smsk,dmsk;
128  for (smsk =  0x01,dmsk=0x80;
129       smsk < 0x100;
130       smsk<<=1   ,dmsk>>=1) {
131    if ((byte & smsk) != 0) {
132      result |= (unsigned char) dmsk;
133    }
134  }
135  return result;
136}
137
138/*=========================================================================*\
139| Function:                                                                 |
140\*-------------------------------------------------------------------------*/
141static rtems_status_code disp_hcms29xx_copy_font
142  (
143/*-------------------------------------------------------------------------*\
144| Purpose:                                                                  |
145|   copy font data from source to dest font structure                       |
146+---------------------------------------------------------------------------+
147| Input Parameters:                                                         |
148\*-------------------------------------------------------------------------*/
149  disp_font_t src,                      /* source font                     */
150  struct disp_font_base *dst,           /* ptr to destination font         */
151  int shift_cnt,                        /* shift count for font            */
152  bool do_rotate                        /* rotate font, if true            */
153)
154/*-------------------------------------------------------------------------*\
155| Return Value:                                                             |
156|    rtems_status_code                                                      |
157\*=========================================================================*/
158{
159
160  rtems_status_code rc = RTEMS_SUCCESSFUL;
161  char *alloc_next = (char *)dst;
162  size_t glyph_idx = 0;
163  int glyph_size;
164  unsigned char byte;
165  int bcnt;
166
167  /*
168   * check parameters
169   */
170  if ((rc == RTEMS_SUCCESSFUL) &&
171      ((src == NULL) ||
172       (dst == NULL))) {
173    rc = RTEMS_INVALID_ADDRESS;
174  }
175  /*
176   * copy font_base structure
177   */
178  if (rc == RTEMS_SUCCESSFUL) {
179    *dst = *src;
180    alloc_next += sizeof(*dst);
181  }
182  /*
183   * for all glyphs: assign own glyph memory
184   */
185  glyph_idx = 0;
186  while ((rc == RTEMS_SUCCESSFUL) &&
187         glyph_idx < (sizeof(src->latin1)/sizeof(src->latin1[0]))) {
188    if (src->latin1[glyph_idx] != NULL) {
189      /*
190       * allocate space for glyph
191       */
192      dst->latin1[glyph_idx] = (struct disp_font_glyph *)alloc_next;
193      alloc_next += sizeof(*(dst->latin1[glyph_idx]));
194      /*
195       * copy source values.
196       * Note: bitmap will be reassigned later
197       */
198      *(struct disp_font_glyph *)(dst->latin1[glyph_idx]) =
199        *(src->latin1[glyph_idx]);
200    }
201    else {
202      dst->latin1[glyph_idx] = NULL;
203    }
204    glyph_idx++;
205  }
206
207  /*
208   * for all glyphs: reassign bitmap
209   */
210  glyph_idx = 0;
211  while ((rc == RTEMS_SUCCESSFUL) &&
212         glyph_idx < (sizeof(src->latin1)/sizeof(src->latin1[0]))) {
213    if (src->latin1[glyph_idx] != NULL) {
214      glyph_size = src->latin1[glyph_idx]->bb.w;
215      /*
216       * allocate space for glyph_bitmap
217       */
218      dst->latin1[glyph_idx]->bitmap = (const unsigned char *) alloc_next;
219      alloc_next += glyph_size;
220      /*
221       * copy/transform bitmap
222       */
223      for (bcnt = 0;bcnt < glyph_size;bcnt++) {
224        if (do_rotate) {
225          byte = src->latin1[glyph_idx]->bitmap[glyph_size - 1 - bcnt];
226          byte = disp_hcms29xx_bitswap(byte);
227        }
228        else {
229          byte = src->latin1[glyph_idx]->bitmap[bcnt];
230        }
231        if (shift_cnt < 0) {
232          byte = byte >> shift_cnt;
233        }
234        else if (shift_cnt > 0) {
235          byte = byte >> shift_cnt;
236        }
237        ((unsigned char *)(dst->latin1[glyph_idx]->bitmap))[bcnt] = byte;
238      }
239    }
240    glyph_idx++;
241  }
242  return rc;
243}
244
245/*=========================================================================*\
246| Function:                                                                 |
247\*-------------------------------------------------------------------------*/
248static rtems_status_code disp_hcms29xx_alloc_copy_font
249  (
250/*-------------------------------------------------------------------------*\
251| Purpose:                                                                  |
252|   copy font data from source to dest font structure, alloc all data       |
253+---------------------------------------------------------------------------+
254| Input Parameters:                                                         |
255\*-------------------------------------------------------------------------*/
256  const disp_font_t src,                /* source font                     */
257  disp_font_t *dst,                     /* ptr to destination font         */
258  int shift_cnt,                        /* shift count for font            */
259  bool do_rotate                        /* rotate font, if true            */
260)
261/*-------------------------------------------------------------------------*\
262| Return Value:                                                             |
263|    rtems_status_code                                                      |
264\*=========================================================================*/
265{
266
267  rtems_status_code rc = RTEMS_SUCCESSFUL;
268  size_t src_size = 0;
269  /*
270   * check parameters
271   */
272  if ((rc == RTEMS_SUCCESSFUL) &&
273      ((src == NULL)
274       || (dst == NULL))) {
275    rc = RTEMS_INVALID_ADDRESS;
276  }
277  /*
278   * determine size of source data
279   */
280  if (rc == RTEMS_SUCCESSFUL) {
281    rc = disp_hcms29xx_font_struct_size(src,&src_size);
282  }
283  /*
284   * allocate proper data area
285   */
286  if (rc == RTEMS_SUCCESSFUL) {
287    *dst = malloc(src_size);
288    if (*dst == NULL) {
289      rc = RTEMS_UNSATISFIED;
290    }
291  }
292  /*
293   * scan through source data, copy to dest
294   */
295  if (rc == RTEMS_SUCCESSFUL) {
296    rc = disp_hcms29xx_copy_font(src,*dst,shift_cnt,do_rotate);
297  }
298  return rc;
299}
300
301/*=========================================
302 * SPI communication functions
303 */
304
305/*=========================================================================*\
306| Function:                                                                 |
307\*-------------------------------------------------------------------------*/
308static rtems_status_code disp_hcms29xx_send_to_display
309  (
310/*-------------------------------------------------------------------------*\
311| Purpose:                                                                  |
312|   request access semaphore to SPI, prepare buffer descriptors, start      |
313|   transfer via SPI to display                                             |
314+---------------------------------------------------------------------------+
315| Input Parameters:                                                         |
316\*-------------------------------------------------------------------------*/
317   disp_hcms29xx_drv_t *softc_ptr,
318   const volatile char *disp_buffer /* start of chars to display (4 chars or 'til \0)*/
319)
320/*-------------------------------------------------------------------------*\
321| Return Value:                                                             |
322|    rtems_status_code                                                      |
323\*=========================================================================*/
324{
325  rtems_status_code rc = RTEMS_SUCCESSFUL;
326  bool char_avail;
327  const struct disp_font_glyph *glyph_ptr;
328  disp_font_t curr_font;
329  int i, ret_cnt;
330  unsigned char c;
331
332  /*
333   * select device, set transfer mode, address device
334   */
335  if (rc == RTEMS_SUCCESSFUL) {
336    rc = rtems_libi2c_send_start(softc_ptr->disp_param.minor);
337  }
338  /*
339   * set transfer mode
340   */
341  if (rc == RTEMS_SUCCESSFUL) {
342    rc = -rtems_libi2c_ioctl(softc_ptr->disp_param.minor,
343                             RTEMS_LIBI2C_IOCTL_SET_TFRMODE,
344                             &spi_disphcms29xx_tfr_mode);
345  }
346
347  /*
348   * address device
349   */
350  if (rc == RTEMS_SUCCESSFUL) {
351    rc = rtems_libi2c_send_addr(softc_ptr->disp_param.minor,true);
352  }
353
354  /*
355   * send data
356   */
357  if (rc == RTEMS_SUCCESSFUL) {
358    curr_font =
359      softc_ptr->disp_param.rotate
360      ? disp_hcms29xx_font_rotate
361      : disp_hcms29xx_font_normal;
362
363    char_avail = true;
364    /*
365     * FIXME: for rotated display, write last character first...
366     * maybe we should copy everything to a common buffer and use
367     * ONE SPI transfer?
368     */
369    for (i = 0;
370         ((rc == RTEMS_SUCCESSFUL) &&
371          (i < DISP_HCMS29XX_DIGIT_CNT));
372          i++) {
373      /* test for end of string... */
374      c = disp_buffer[i]; /* perform consistent read of disp_buffer */
375      if (char_avail && (c == '\0')) {
376        char_avail = false;
377      }
378      glyph_ptr = (char_avail
379                   ? curr_font->latin1[c]
380                   : NULL);
381      if (glyph_ptr == NULL) {
382        glyph_ptr = curr_font->latin1[' '];
383      }
384
385      /*
386       * send 5 bytes from (char *)glyph_ptr->bitmap to SPI
387       */
388      if (rc == RTEMS_SUCCESSFUL) {
389        ret_cnt = rtems_libi2c_write_bytes(softc_ptr->disp_param.minor,
390                                           glyph_ptr->bitmap,5);
391        if (ret_cnt < 0) {
392          rc = -ret_cnt;
393        }
394      }
395    }
396  }
397  /*
398   * finish transfer
399   */
400  if (rc == RTEMS_SUCCESSFUL) {
401    rc = rtems_libi2c_send_stop(softc_ptr->disp_param.minor);
402  }
403
404  return rc;
405}
406
407/*=========================================================================*\
408| Function:                                                                 |
409\*-------------------------------------------------------------------------*/
410static rtems_status_code disp_hcms29xx_send_to_control
411  (
412/*-------------------------------------------------------------------------*\
413| Purpose:                                                                  |
414|   request access semaphore to SPI, prepare buffer descriptors, start      |
415|   transfer via SPI to display                                             |
416+---------------------------------------------------------------------------+
417| Input Parameters:                                                         |
418\*-------------------------------------------------------------------------*/
419   disp_hcms29xx_drv_t *softc_ptr,
420   int pwm,   /* value for pwm of LEDs, 0..15 */
421   int peak,  /* value for peak current for LEDs, 0..3 */
422   int sleep, /* value to make display "sleep" (0..1 */
423   int div,   /* divider for external osc input, unused here */
424   int chain  /* mode to drive other displays, unused here */
425)
426/*-------------------------------------------------------------------------*\
427| Return Value:                                                             |
428|    rtems_status_code                                                      |
429\*=========================================================================*/
430{
431  rtems_status_code rc = RTEMS_SUCCESSFUL;
432  int run, ret_cnt;
433  uint8_t ctrl_buffer;
434
435  /* two accesses, control word 0 and 1 */
436  for (run = 0;
437       ((rc == RTEMS_SUCCESSFUL) && (run <= 1));
438       run++) {
439    if (rc == RTEMS_SUCCESSFUL) {
440      if (run == 0) {
441        ctrl_buffer =
442          (0              << 7) |
443          ((sleep & 0x01) << 6) |
444          ((peak  & 0x03) << 4) |
445          ((pwm & 0x0f)   << 0);
446      }
447      else {
448        ctrl_buffer =
449          (1              << 7) |
450          ((div   & 0x01) << 1) |
451          ((chain & 0x01) << 0);
452      }
453      /*
454       * select device, set transfer mode, address device
455       */
456      if (rc == RTEMS_SUCCESSFUL) {
457        rc = rtems_libi2c_send_start(softc_ptr->disp_param.minor);
458      }
459      /*
460       * set transfer mode
461       */
462      if (rc == RTEMS_SUCCESSFUL) {
463        rc = -rtems_libi2c_ioctl(softc_ptr->disp_param.minor,
464                                 RTEMS_LIBI2C_IOCTL_SET_TFRMODE,
465                                 &spi_disphcms29xx_tfr_mode);
466      }
467
468      /*
469       * address device
470       */
471      if (rc == RTEMS_SUCCESSFUL) {
472        rc = rtems_libi2c_send_addr(softc_ptr->disp_param.minor,true);
473      }
474
475      /*
476       * send 1 byte from ctrl_buffer
477       */
478      if (rc == RTEMS_SUCCESSFUL) {
479        ret_cnt = rtems_libi2c_write_bytes(softc_ptr->disp_param.minor,
480                                           &ctrl_buffer,1);
481        if (ret_cnt < 0) {
482          rc = -ret_cnt;
483        }
484      }
485    }
486  } /* next run ... */
487
488  /*
489   * finish transfer
490   */
491  if (rc == RTEMS_SUCCESSFUL) {
492    rc = rtems_libi2c_send_stop(softc_ptr->disp_param.minor);
493  }
494
495  return rc;
496}
497
498/*=========================================================================*\
499| Function:                                                                 |
500\*-------------------------------------------------------------------------*/
501static rtems_timer_service_routine disp_hcms29xx_timer_sr
502/*-------------------------------------------------------------------------*\
503| Purpose:                                                                  |
504|   this task updates the string in the display                             |
505+---------------------------------------------------------------------------+
506| Input Parameters:                                                         |
507\*-------------------------------------------------------------------------*/
508(
509 rtems_id id, /* ID of timer, not used  */
510 void * arg   /* calling arg: softc_ptr */
511)
512/*-------------------------------------------------------------------------*\
513| Return Value:                                                             |
514|    <none used>                                                            |
515\*=========================================================================*/
516{
517  rtems_status_code rc = RTEMS_SUCCESSFUL;
518  disp_hcms29xx_drv_t *softc_ptr = arg;
519
520
521  if (rc == RTEMS_SUCCESSFUL) {
522    rc = rtems_event_send(softc_ptr->disp_param.task_id,
523                          DISP_HCMS29XX_EVENT_TIMER);
524  }
525}
526
527/*=========================================================================*\
528| Function:                                                                 |
529\*-------------------------------------------------------------------------*/
530static rtems_task disp_hcms29xx_update_task
531  (
532/*-------------------------------------------------------------------------*\
533| Purpose:                                                                  |
534|   this task updates the string in the display                             |
535+---------------------------------------------------------------------------+
536| Input Parameters:                                                         |
537\*-------------------------------------------------------------------------*/
538   rtems_task_argument argument
539)
540/*-------------------------------------------------------------------------*\
541| Return Value:                                                             |
542|    <never exits>                                                          |
543\*=========================================================================*/
544{
545  rtems_event_set  my_events;
546  rtems_status_code rc = RTEMS_SUCCESSFUL;
547  int disp_offset = 0;
548  rtems_id disp_hcms29xx_timer_id;
549  disp_hcms29xx_drv_t *softc_ptr = &disp_hcms29xx_drv_tbl;
550
551  /*
552   * initialize display:
553   */
554  /*
555   * set control attributes for display
556   * maximum brightness...
557   */
558  if (rc == RTEMS_SUCCESSFUL) {
559    rc = disp_hcms29xx_send_to_control(softc_ptr,
560                                       14,3,1,0,0);/* pwm/peak/nosleep/div/chain */
561  }
562
563  /*
564   * set display to blank
565   */
566  if (rc == RTEMS_SUCCESSFUL) {
567    rc = disp_hcms29xx_send_to_display(softc_ptr,
568                                       "");
569  }
570
571  /*
572   * create timer for scrolling
573   */
574  if (rc == RTEMS_SUCCESSFUL) {
575    rc = rtems_timer_create(DISP_HCMS29XX_TIMER_NAME,
576                            &disp_hcms29xx_timer_id);
577  }
578
579  while (rc == RTEMS_SUCCESSFUL) {
580    /*
581     * wait for any event
582     */
583    rc = rtems_event_receive(DISP_HCMS29XX_EVENT_NEWSTR |
584                             DISP_HCMS29XX_EVENT_TIMER ,
585                             RTEMS_WAIT | RTEMS_EVENT_ANY,
586                             RTEMS_NO_TIMEOUT,
587                             &my_events);
588    if (my_events & DISP_HCMS29XX_EVENT_NEWSTR) {
589      /*
590       * fetch new string consistently into local buffer
591       */
592      if (rc == RTEMS_SUCCESSFUL) {
593        rc = rtems_semaphore_obtain(softc_ptr->disp_param.trns_sema_id,
594                                    RTEMS_WAIT,RTEMS_NO_TIMEOUT);
595      }
596      if (rc == RTEMS_SUCCESSFUL) {
597        strncpy(softc_ptr->disp_param.disp_buffer,
598                softc_ptr->disp_param.trns_buffer,
599                sizeof(softc_ptr->disp_param.disp_buffer));
600        softc_ptr->disp_param.disp_buffer[sizeof(softc_ptr->disp_param.disp_buffer)-1] = '\0';
601        softc_ptr->disp_param.disp_buf_cnt =
602          (int) strlen(softc_ptr->disp_param.disp_buffer);
603      }
604      if (rc == RTEMS_SUCCESSFUL) {
605        rc = rtems_semaphore_release(softc_ptr->disp_param.trns_sema_id);
606      }
607      /*
608       * set initial offset to negative value
609       * to make string static for some ticks
610       */
611      disp_offset = -4;
612    }
613    if (my_events & DISP_HCMS29XX_EVENT_TIMER) {
614      /*
615       * increase disp_offset, if possible, otherwise reset it
616       */
617      if ((disp_offset < 0) ||
618          (disp_offset < softc_ptr->disp_param.disp_buf_cnt-
619           DISP_HCMS29XX_DIGIT_CNT/2)) {
620        disp_offset++;
621      }
622      else {
623        disp_offset = -4;
624      }
625    }
626    /*
627     * display string, starting from disp_offset
628     */
629    if (disp_offset < 0) {
630      rc = disp_hcms29xx_send_to_display(softc_ptr,
631                                         softc_ptr->disp_param.disp_buffer);
632    }
633    else if (disp_offset
634             < (softc_ptr->disp_param.disp_buf_cnt - DISP_HCMS29XX_DIGIT_CNT)) {
635      rc = disp_hcms29xx_send_to_display(softc_ptr,
636                                         softc_ptr->disp_param.disp_buffer+disp_offset);
637    }
638    else {
639      rc = disp_hcms29xx_send_to_display(softc_ptr,
640                                         softc_ptr->disp_param.disp_buffer
641                                         + softc_ptr->disp_param.disp_buf_cnt
642                                         - DISP_HCMS29XX_DIGIT_CNT);
643    }
644    /*
645     * activate timer, if needed
646     */
647    if (rc == RTEMS_SUCCESSFUL) {
648      if (softc_ptr->disp_param.disp_buf_cnt > DISP_HCMS29XX_DIGIT_CNT) {
649        rc = rtems_timer_fire_after(disp_hcms29xx_timer_id,
650                                    50,
651                                    disp_hcms29xx_timer_sr,
652                                    NULL);
653      }
654      else {
655        rc = rtems_timer_cancel(disp_hcms29xx_timer_id);
656      }
657    }
658  }
659  /*
660   * FIXME: display task is dead...
661   */
662}
663
664/*=========================================================================*\
665| Function:                                                                 |
666\*-------------------------------------------------------------------------*/
667static rtems_status_code disp_hcms29xx_update
668  (
669/*-------------------------------------------------------------------------*\
670| Purpose:                                                                  |
671|   move given string to display task                                       |
672+---------------------------------------------------------------------------+
673| Input Parameters:                                                         |
674\*-------------------------------------------------------------------------*/
675   disp_hcms29xx_drv_t *softc_ptr,
676   const char *src
677)
678/*-------------------------------------------------------------------------*\
679| Return Value:                                                             |
680|    rtems_status_code                                                      |
681\*=========================================================================*/
682{
683  rtems_status_code rc = RTEMS_SUCCESSFUL;
684
685  /*
686   * obtain trns semaphore
687   */
688  if (rc == RTEMS_SUCCESSFUL) {
689    rc = rtems_semaphore_obtain(softc_ptr->disp_param.trns_sema_id,
690                                RTEMS_WAIT,RTEMS_NO_TIMEOUT);
691  }
692  /*
693   * copy string...
694   */
695  strncpy(softc_ptr->disp_param.trns_buffer,src,
696          sizeof(softc_ptr->disp_param.trns_buffer));
697  softc_ptr->disp_param.trns_buffer[sizeof(softc_ptr->disp_param.trns_buffer)-1] = '\0';
698
699  /*
700   * release trns semaphore
701   */
702  if (rc == RTEMS_SUCCESSFUL) {
703    rc = rtems_semaphore_release(softc_ptr->disp_param.trns_sema_id);
704  }
705
706  /*
707   * send event to task
708   */
709  if (rc == RTEMS_SUCCESSFUL) {
710    rc = rtems_event_send(softc_ptr->disp_param.task_id,
711                          DISP_HCMS29XX_EVENT_NEWSTR);
712  }
713
714  return rc;
715}
716
717/*=========================================================================*\
718| Function:                                                                 |
719\*-------------------------------------------------------------------------*/
720rtems_device_driver disp_hcms29xx_dev_initialize
721  (
722/*-------------------------------------------------------------------------*\
723| Purpose:                                                                  |
724|   prepare the display device driver to accept write calls                 |
725|   register device with its name                                           |
726+---------------------------------------------------------------------------+
727| Input Parameters:                                                         |
728\*-------------------------------------------------------------------------*/
729  rtems_device_major_number  major,
730  rtems_device_minor_number  minor,
731  void                      *arg
732)
733/*-------------------------------------------------------------------------*\
734| Return Value:                                                             |
735|    rtems_status_code                                                      |
736\*=========================================================================*/
737/*
738 * Initialize and register the device
739 */
740{
741  rtems_status_code rc = RTEMS_SUCCESSFUL;
742  disp_hcms29xx_drv_t *softc_ptr = &disp_hcms29xx_drv_tbl;
743
744  /*
745   * initialize font management
746   * FIXME: check, that default glyph exists
747   * FIXME: check font size to be 5x7
748   */
749  /*
750   * translate font according to direction/baseline
751   */
752  if (rc == RTEMS_SUCCESSFUL) {
753    rc = disp_hcms29xx_alloc_copy_font(
754                               &FONT_BASE,
755                               &disp_hcms29xx_font_normal,
756                               FONT_BASE.descent, /* shift to visibility... */
757                               FALSE); /* do not rotate */
758  }
759  /* FIXME: translate font for rotation */
760  if (rc == RTEMS_SUCCESSFUL) {
761    rc = disp_hcms29xx_alloc_copy_font(&FONT_BASE,
762                               &disp_hcms29xx_font_rotate,
763                               0, /* do not shift */
764                               true); /* rotate font */
765  }
766  /*
767   * create the trns_buffer semaphore
768   */
769  if (rc == RTEMS_SUCCESSFUL) {
770    rc = rtems_semaphore_create (DISP_HCMS29XX_TRNS_SEMA_NAME,1,
771                                     RTEMS_PRIORITY
772                                     |RTEMS_BINARY_SEMAPHORE
773                                     |RTEMS_INHERIT_PRIORITY
774                                     |RTEMS_NO_PRIORITY_CEILING
775                                     |RTEMS_LOCAL,
776                                     0,
777                                     &softc_ptr->disp_param.trns_sema_id);
778  }
779
780  /*
781   * create and start display task
782   */
783  if (rc == RTEMS_SUCCESSFUL) {
784    rc = rtems_task_create(DISP_HCMS29XX_TASK_NAME,
785                           20,
786                           RTEMS_MINIMUM_STACK_SIZE,
787                           RTEMS_INTERRUPT_LEVEL(0) | RTEMS_TIMESLICE,
788                           RTEMS_DEFAULT_ATTRIBUTES,
789                           &softc_ptr->disp_param.task_id);
790  }
791  if (rc == RTEMS_SUCCESSFUL) {
792    rc = rtems_task_start(softc_ptr->disp_param.task_id,
793                          disp_hcms29xx_update_task,0);
794  }
795  return rc;
796}
797
798/*=========================================================================*\
799| Function:                                                                 |
800\*-------------------------------------------------------------------------*/
801rtems_device_driver disp_hcms29xx_dev_open
802(
803/*-------------------------------------------------------------------------*\
804| Purpose:                                                                  |
805|   open the display device                                                 |
806+---------------------------------------------------------------------------+
807| Input Parameters:                                                         |
808\*-------------------------------------------------------------------------*/
809  rtems_device_major_number  major,
810  rtems_device_minor_number  minor,
811  void                      *arg
812)
813/*-------------------------------------------------------------------------*\
814| Return Value:                                                             |
815|    rtems_status_code                                                      |
816\*=========================================================================*/
817{
818  disp_hcms29xx_drv_t *softc_ptr = &disp_hcms29xx_drv_tbl;
819  /*
820   * ensure, that disp_hcms29xx device is assumed to be empty
821   */
822  softc_ptr->disp_param.dev_buf_cnt = 0;
823
824  return RTEMS_SUCCESSFUL;
825}
826
827/*=========================================================================*\
828| Function:                                                                 |
829\*-------------------------------------------------------------------------*/
830rtems_device_driver disp_hcms29xx_dev_write
831(
832/*-------------------------------------------------------------------------*\
833| Purpose:                                                                  |
834|   write to display device                                                 |
835+---------------------------------------------------------------------------+
836| Input Parameters:                                                         |
837\*-------------------------------------------------------------------------*/
838  rtems_device_major_number  major,
839  rtems_device_minor_number  minor,
840  void                      *arg
841)
842/*-------------------------------------------------------------------------*\
843| Return Value:                                                             |
844|    rtems_status_code                                                      |
845\*=========================================================================*/
846{
847  rtems_libio_rw_args_t *args = arg;
848  uint32_t cnt;
849  disp_hcms29xx_drv_t *softc_ptr = &disp_hcms29xx_drv_tbl;
850
851  for (cnt = 0;cnt < args->count;cnt++) {
852    /*
853     * accumulate characters written into display dev buffer
854     */
855    if (((softc_ptr->disp_param.dev_buf_cnt > 0)
856        &&((args->buffer[cnt] == '\n')
857           || (args->buffer[cnt] == '\0'))
858         )
859        ||( softc_ptr->disp_param.dev_buf_cnt >=
860            (int) sizeof(softc_ptr->disp_param.dev_buffer) - 1)) {
861      softc_ptr->disp_param.dev_buffer[softc_ptr->disp_param.dev_buf_cnt] = '\0';
862      /*
863       * transfer string to display string, redisplay it...
864       */
865      disp_hcms29xx_update(softc_ptr,softc_ptr->disp_param.dev_buffer);
866      softc_ptr->disp_param.dev_buf_cnt = 0;
867    }
868    /*
869     * write to dev_buf, if '\n' occured or display device buffer is full
870     */
871    if ((args->buffer[cnt] != '\n') &&
872        (args->buffer[cnt] != '\0')) {
873      softc_ptr->disp_param.dev_buffer[softc_ptr->disp_param.dev_buf_cnt++] =
874        args->buffer[cnt];
875    }
876  }
877  args->bytes_moved = args->count;
878
879  return RTEMS_SUCCESSFUL;
880}
881
882/*=========================================================================*\
883| Function:                                                                 |
884\*-------------------------------------------------------------------------*/
885rtems_device_driver disp_hcms29xx_dev_close
886(
887/*-------------------------------------------------------------------------*\
888| Purpose:                                                                  |
889|   close the display device                                                |
890+---------------------------------------------------------------------------+
891| Input Parameters:                                                         |
892\*-------------------------------------------------------------------------*/
893  rtems_device_major_number  major,
894  rtems_device_minor_number  minor,
895  void                      *arg
896)
897/*-------------------------------------------------------------------------*\
898| Return Value:                                                             |
899|    rtems_status_code                                                      |
900\*=========================================================================*/
901{
902
903  return RTEMS_SUCCESSFUL;
904}
905
906/*
907 * driver operation tables
908 */
909static rtems_driver_address_table disp_hcms29xx_ops = {
910  .initialization_entry = disp_hcms29xx_dev_initialize,
911  .open_entry =           disp_hcms29xx_dev_open,
912  .write_entry =          disp_hcms29xx_dev_write,
913  .close_entry =          disp_hcms29xx_dev_close
914};
915
916
917static disp_hcms29xx_drv_t disp_hcms29xx_drv_tbl = {
918  {/* public fields */
919    .ops =         &disp_hcms29xx_ops,
920    .size =        sizeof (disp_hcms29xx_drv_t),
921  },
922  { /* our private fields */
923    0,
924    { 0 },
925    0,
926    { 0 },
927    { 0 },
928    0,
929    0,
930    0,
931    false
932  }
933};
934
935rtems_libi2c_drv_t *disp_hcms29xx_driver_descriptor =
936  &disp_hcms29xx_drv_tbl.libi2c_drv_entry;
937
Note: See TracBrowser for help on using the repository browser.