1 /***************************************************************************//**
2 * \file cy_seglcd.c
3 * \version 1.10
4 *
5 * \brief
6 * Provides an API implementation of the SegLCD driver
7 *
8 ********************************************************************************
9 * \copyright
10 * Copyright 2019-2020 Cypress Semiconductor Corporation
11 * SPDX-License-Identifier: Apache-2.0
12 *
13 * Licensed under the Apache License, Version 2.0 (the "License");
14 * you may not use this file except in compliance with the License.
15 * You may obtain a copy of the License at
16 *
17 *     http://www.apache.org/licenses/LICENSE-2.0
18 *
19 * Unless required by applicable law or agreed to in writing, software
20 * distributed under the License is distributed on an "AS IS" BASIS,
21 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 * See the License for the specific language governing permissions and
23 * limitations under the License.
24 *******************************************************************************/
25 
26 #include "cy_device.h"
27 
28 #if defined (CY_IP_MXLCD)
29 
30 #include "cy_seglcd.h"
31 #include "cy_sysclk.h"
32 
33 CY_MISRA_DEVIATE_BLOCK_START('MISRA C-2012 Rule 11.3', 28, \
34 'LCD_Type will typecast to either LCD_V1_Type or LCD_V2_Type but not both on PDL initialization based on the target device at compile time.')
35 
36 #define CY_SEGLCD_ENABLE_Msk                (LCD_CONTROL_LS_EN_Msk | LCD_CONTROL_HS_EN_Msk)
37 #define CY_SEGLCD_NIBBLE                    (4UL)
38 
39 #define CY_SEGLCD_DIV_MAX                   (0x0000FFFFUL) /* The max. divider values */
40 #define CY_SEGLCD_DIV_MAX_LS_VER1           (0x000000FFUL) /* The max. divider values for Low Speed mode for MXLCD_ver1 */
41 
42 #define CY_SEGLCD_SYM_BIT_IDX_Pos           (0U)
43 #define CY_SEGLCD_SYM_BIT_IDX_Msk           ((uint32_t) 0x00000007UL << CY_SEGLCD_SYM_BIT_IDX_Pos)
44 #define CY_SEGLCD_SYM_BYTE_IDX_Pos          (3U)
45 #define CY_SEGLCD_SYM_BYTE_IDX_Msk          ((uint32_t) 0x00001FFFUL << CY_SEGLCD_SYM_BYTE_IDX_Pos)
46 
47 #define CY_SEGLCD_PIX_Pos(pixel)            ((CY_SEGLCD_EXTR_NBL(pixel) * CY_SEGLCD_NIBBLE) + \
48                                              (CY_SEGLCD_EXTR_COM(pixel) % CY_SEGLCD_NIBBLE))
49 #define CY_SEGLCD_PIX_Msk(pixel)            ((uint32_t)(1UL << CY_SEGLCD_PIX_Pos(pixel)))
50 
51 #define CY_SEGLCD_REVISION(base)            (_FLD2VAL(LCD_ID_REVISION, LCD_ID(base)))
52 #define CY_SEGLCD_REV_1(base)               (1UL == CY_SEGLCD_REVISION(base))
53 #define CY_SEGLCD_IS_ENABLED(base)          (0UL != (LCD_CONTROL(base) & CY_SEGLCD_ENABLE_Msk))
54 #define CY_SEGLCD_IS_MSK_VALID(pixel)       (0UL == ((pixel) & ~(CY_SEGLCD_COM_Msk | CY_SEGLCD_OCT_Msk | CY_SEGLCD_NBL_Msk)))
55 #define CY_SEGLCD_IS_COM_VALID(pixel)       (LCD_COM_NUM > CY_SEGLCD_EXTR_COM(pixel))
56 #define CY_SEGLCD_IS_PIX_VALID(pixel)       (CY_SEGLCD_IS_MSK_VALID(pixel) && CY_SEGLCD_IS_COM_VALID(pixel))
57 
58 
59 #define CY_SEGLCD_COM_NUM_MIN               (2U)
60 #define CY_SEGLCD_COM_NUM_MAX               (LCD_COM_NUM)
61 #define CY_SEGLCD_IS_COM_NUM_VALID(num)     ((CY_SEGLCD_COM_NUM_MIN <= (num)) && ((num) <= CY_SEGLCD_COM_NUM_MAX))
62 
63 #define CY_SEGLCD_IS_BASIC(type)            (((uint16_t)CY_SEGLCD_7SEG  == (type)) || \
64                                              ((uint16_t)CY_SEGLCD_14SEG == (type)) || \
65                                              ((uint16_t)CY_SEGLCD_16SEG == (type)) || \
66                                              ((uint16_t)CY_SEGLCD_5X8DM == (type)))
67 
68 #define CY_SEGLCD_IS_PIXMAP(disp)           ((NULL != (disp)) && \
69                                              (NULL != (disp)->pixMap))
70 
71 #define CY_SEGLCD_IS_SYMBOLIC(disp, pos)    (CY_SEGLCD_IS_PIXMAP(disp) && \
72                                              (NULL != (disp)->font) && \
73                                              (NULL != (disp)->font->fontMap) && \
74                                              ((uint32_t)CY_SEGLCD_BAR < (disp)->type) && \
75                                              (((pos) < (disp)->symNum)))
76 
77 #define CY_SEGLCD_IS_ASCII(disp, pos)       (CY_SEGLCD_IS_SYMBOLIC(disp, pos) && \
78                                              ((disp)->font->ascii))
79 
80 #define CY_SEGLCD_IS_BARGRAPH(disp, pos)    (CY_SEGLCD_IS_PIXMAP(disp) && \
81                                              ((uint32_t)CY_SEGLCD_BAR == (disp)->type) && \
82                                              (((pos) < (disp)->symNum)))
83 
84 #define CY_SEGLCD_IS_SPEED_VALID(speed)     ((CY_SEGLCD_SPEED_LOW  == (speed)) || \
85                                              (CY_SEGLCD_SPEED_HIGH == (speed)))
86 
87 #define CY_SEGLCD_IS_WAVE_VALID(wave)       ((CY_SEGLCD_TYPE_A == (wave)) || \
88                                              (CY_SEGLCD_TYPE_B == (wave)))
89 
90 #define CY_SEGLCD_IS_DRIVE_VALID(drive)     ((CY_SEGLCD_PWM         == (drive)) || \
91                                              (CY_SEGLCD_CORRELATION == (drive)))
92 
93 #define CY_SEGLCD_IS_BIAS_4_5_SUPPORTED(base,speed) ((CY_SEGLCD_REV_1(base)) ? (CY_SEGLCD_SPEED_HIGH == (speed)) : true)
94 
95 #define CY_SEGLCD_IS_BIAS_VALID(base,bias,speed) ((CY_SEGLCD_BIAS_HALF   == (bias))  || \
96                                                   (CY_SEGLCD_BIAS_THIRD  == (bias))  || \
97   (CY_SEGLCD_IS_BIAS_4_5_SUPPORTED(base,speed) && (CY_SEGLCD_BIAS_FOURTH == (bias))) || \
98   (CY_SEGLCD_IS_BIAS_4_5_SUPPORTED(base,speed) && (CY_SEGLCD_BIAS_FIFTH  == (bias))))
99 
100 #define CY_SEGLCD_IS_LSCLK_VALID(lsClk)     ((CY_SEGLCD_LSCLK_LF == (lsClk)) || \
101                                              (CY_SEGLCD_LSCLK_MF == (lsClk)))
102 
103 #define CY_SEGLCD_FR_RATE_MIN               (30U)
104 #define CY_SEGLCD_FR_RATE_MAX               (150U)
105 #define CY_SEGLCD_IS_RATE_VALID(frRate)     (((frRate) >= CY_SEGLCD_FR_RATE_MIN) && ((frRate) <= CY_SEGLCD_FR_RATE_MAX))
106 
107 #define CY_SEGLCD_CNTR_MAX                  (100UL)
108 #define CY_SEGLCD_IS_CNTR_VALID(contrast)   (((uint32_t)(contrast)) <= CY_SEGLCD_CNTR_MAX)
109 
110 #define CY_SEGLCD_FREQ_MIN                  (10000UL)
111 #define CY_SEGLCD_FREQ_MAX                  (100000000UL)
112 #define CY_SEGLCD_IS_FREQ_VALID(freq)       (((freq) >= CY_SEGLCD_FREQ_MIN) && ((freq) <= CY_SEGLCD_FREQ_MAX))
113 
114 #define CY_SEGLCD_SPACE(disp)               (((disp)->font->ascii) ? ' ' : CY_SEGLCD_NUM_BLANK)
115 
116 /* The timeout value for Low Speed mode enable/disable procedures, two ILO clock periods, in uSeconds */
117 #define CY_SEGLCD_TIMEOUT ((2U * 1000000UL) / CY_SYSCLK_ILO_FREQ)
118 
119 
120 static volatile uint32_t * GetDataRegPtr(LCD_Type * base, uint32_t pixel);
121 static void InvClrData(LCD_Type * base, bool inv);
122 static char_t NumToChar(uint32_t value);
123 
124 
125 static const uint8_t fontMap7[] = /* Apparently the 7-segment font character code fits into a single byte so the 'font map symbol size' is not used here */
126 /*'0'   '1'   '2'   '3'   '4'   '5'   '6'   '7'   '8'   '9'   'A'   'B'   'C'   'D'   'E'   'F' 'blank'*/
127 {0x3FU,0x06U,0x5BU,0x4FU,0x66U,0x6DU,0x7DU,0x07U,0x7FU,0x6FU,0x77U,0x7CU,0x39U,0x5EU,0x79U,0x71U,0x00U};
128 
129 const cy_stc_seglcd_font_t cy_segLCD_7SegFont =
130 {
131     .first   = '\0',
132     .last    = CY_SEGLCD_NUM_BLANK,
133     .ascii   = false,
134     .fontMap = fontMap7
135 };
136 
137 
138 static const uint8_t fontMap14[][CY_SEGLCD_14SEG_FONTMAP_SIZE] =
139 {
140     /*  space           !             "             #             $             %             &             '     */
141     {0x00U,0x00U},{0x06U,0x00U},{0x20U,0x01U},{0xFFU,0x3FU},{0x6DU,0x15U},{0xE4U,0x2EU},{0x8DU,0x2AU},{0x00U,0x02U},
142     /*    (             )             *             +             ,             -             .             /     */
143     {0x00U,0x0AU},{0x80U,0x20U},{0xC0U,0x3FU},{0x40U,0x15U},{0x00U,0x20U},{0x40U,0x04U},{0x58U,0x10U},{0x00U,0x22U},
144     /*    0             1             2             3             4             5             6             7     */
145     {0x3FU,0x22U},{0x06U,0x02U},{0x5BU,0x04U},{0x0FU,0x04U},{0x66U,0x04U},{0x69U,0x08U},{0x7DU,0x04U},{0x01U,0x12U},
146     /*    8             9             :             ;             <             =             >             ?     */
147     {0x7FU,0x04U},{0x6FU,0x04U},{0x00U,0x11U},{0x00U,0x21U},{0x00U,0x0AU},{0x48U,0x04U},{0x80U,0x20U},{0x23U,0x14U},
148     /*    @             A             B             C             D             E             F             G     */
149     {0x3BU,0x05U},{0x77U,0x04U},{0x0FU,0x15U},{0x39U,0x00U},{0x0FU,0x11U},{0x79U,0x00U},{0x71U,0x00U},{0x3DU,0x04U},
150     /*    H             I             J             K             L             M             N             O     */
151     {0x76U,0x04U},{0x00U,0x11U},{0x1EU,0x00U},{0x70U,0x0AU},{0x38U,0x00U},{0xB6U,0x02U},{0xB6U,0x08U},{0x3FU,0x00U},
152     /*    P             Q             R             S             T             U             V             W     */
153     {0x73U,0x04U},{0x3FU,0x08U},{0x73U,0x0CU},{0x6DU,0x04U},{0x01U,0x11U},{0x3EU,0x00U},{0x30U,0x22U},{0x36U,0x28U},
154     /*    X             Y             Z             [             \             ]             ^             _     */
155     {0x80U,0x2AU},{0x80U,0x12U},{0x09U,0x22U},{0x39U,0x00U},{0x80U,0x08U},{0x0FU,0x00U},{0x03U,0x00U},{0x08U,0x00U},
156     /*    `             a             b             c             d             e             f             g     */
157     {0x00U,0x02U},{0x77U,0x04U},{0x0FU,0x15U},{0x39U,0x00U},{0x0FU,0x11U},{0x79U,0x00U},{0x71U,0x00U},{0x3DU,0x04U},
158     /*    h             i             j             k             l             m             n             o     */
159     {0x76U,0x04U},{0x00U,0x11U},{0x1EU,0x00U},{0x70U,0x0AU},{0x38U,0x00U},{0xB6U,0x02U},{0xB6U,0x08U},{0x3FU,0x00U},
160     /*    p             q             r             s             t             u             v             w     */
161     {0x73U,0x04U},{0x3FU,0x08U},{0x73U,0x0CU},{0x6DU,0x04U},{0x01U,0x11U},{0x3EU,0x00U},{0x30U,0x22U},{0x36U,0x28U},
162     /*    x             y             z             {             |             }             ~    */
163     {0x80U,0x2AU},{0x80U,0x12U},{0x09U,0x22U},{0x00U,0x0EU},{0x00U,0x11U},{0xC0U,0x20U},{0x52U,0x04U}
164 };
165 
166 const cy_stc_seglcd_font_t cy_segLCD_14SegFont =
167 {
168     .first   = ' ',
169     .last    = '~',
170     .ascii   = true,
171     .fontMap = (uint8_t*)fontMap14
172 };
173 
174 
175 static const uint8_t fontMap16[][CY_SEGLCD_16SEG_FONTMAP_SIZE] =
176 {
177     /*  space           !             "             #             $             %             &             '     */
178     {0x00U,0x00U},{0x0CU,0x00U},{0x80U,0x04U},{0xFFU,0xFFU},{0xBBU,0x55U},{0x99U,0xDDU},{0x3BU,0xAAU},{0x00U,0x08U},
179     /*    (             )             *             +             ,             -             .             /     */
180     {0x00U,0x28U},{0x00U,0x82U},{0x00U,0xFFU},{0x00U,0x55U},{0x00U,0x80U},{0x00U,0x11U},{0x60U,0x41U},{0x00U,0x88U},
181     /*    0             1             2             3             4             5             6             7     */
182     {0xFFU,0x88U},{0x0CU,0x00U},{0x77U,0x11U},{0x3FU,0x10U},{0x8CU,0x11U},{0xB3U,0x21U},{0xFBU,0x11U},{0x03U,0x48U},
183     /*    8             9             :             ;             <             =             >             ?     */
184     {0xFFU,0x11U},{0xBFU,0x11U},{0x00U,0x44U},{0x00U,0x84U},{0x00U,0x28U},{0x30U,0x11U},{0x00U,0x82U},{0x87U,0x50U},
185     /*    @             A             B             C             D             E             F             G     */
186     {0xF7U,0x14U},{0xCFU,0x11U},{0x3FU,0x54U},{0xF3U,0x00U},{0x3FU,0x44U},{0xF3U,0x01U},{0xC3U,0x01U},{0xFBU,0x10U},
187     /*    H             I             J             K             L             M             N             O     */
188     {0xCCU,0x11U},{0x00U,0x44U},{0x7EU,0x00U},{0xC0U,0x29U},{0xF0U,0x00U},{0xCCU,0x0AU},{0xCCU,0x22U},{0xFFU,0x00U},
189     /*    P             Q             R             S             T             U             V             W     */
190     {0xC7U,0x11U},{0xFFU,0x20U},{0xC7U,0x31U},{0xBBU,0x11U},{0x03U,0x44U},{0xFCU,0x00U},{0xC0U,0x88U},{0xCCU,0xA0U},
191     /*    X             Y             Z             [             \             ]             ^             _     */
192     {0x00U,0xAAU},{0x00U,0x4AU},{0x33U,0x88U},{0x12U,0x44U},{0x00U,0x22U},{0x21U,0x44U},{0x06U,0x00U},{0x30U,0x00U},
193     /*    `             a             b             c             d             e             f             g     */
194     {0x00U,0x08U},{0xCFU,0x11U},{0x3FU,0x54U},{0xF3U,0x00U},{0x3FU,0x44U},{0xF3U,0x01U},{0xC3U,0x01U},{0xFBU,0x10U},
195     /*    h             i             j             k             l             m             n             o     */
196     {0xCCU,0x11U},{0x00U,0x44U},{0x7EU,0x00U},{0xC0U,0x29U},{0xF0U,0x00U},{0xCCU,0x0AU},{0xCCU,0x22U},{0xFFU,0x00U},
197     /*    p             q             r             s             t             u             v             w     */
198     {0xC7U,0x11U},{0xFFU,0x20U},{0xC7U,0x31U},{0xBBU,0x11U},{0x03U,0x44U},{0xFCU,0x00U},{0xC0U,0x88U},{0xCCU,0xA0U},
199     /*    x             y             z             {             |             }             ~    */
200     {0x00U,0xAAU},{0x00U,0x4AU},{0x33U,0x88U},{0x00U,0x38U},{0x00U,0x44U},{0x00U,0x83U},{0x44U,0x11U}
201 };
202 
203 const cy_stc_seglcd_font_t cy_segLCD_16SegFont =
204 {
205     .first   = ' ',
206     .last    = '~',
207     .ascii   = true,
208     .fontMap = (uint8_t*)fontMap16
209 };
210 
211 
212 static const uint8_t fontMap5x8[][CY_SEGLCD_5X8DM_FONTMAP_SIZE] =
213 {
214     /*           space                             !                               "                               #              */
215     {0x00U,0x00U,0x00U,0x00U,0x00U},{0x00U,0x00U,0x4FU,0x00U,0x00U},{0x00U,0x07U,0x00U,0x07U,0x00U},{0x14U,0x7FU,0x14U,0x7FU,0x14U},
216     /*             $                               %                               &                               '               */
217     {0x24U,0x2AU,0x7FU,0x2AU,0x12U},{0x23U,0x13U,0x08U,0x64U,0x62U},{0x36U,0x49U,0x55U,0x22U,0x50U},{0x00U,0x05U,0x03U,0x00U,0x00U},
218     /*             (                               )                               *                               +             */
219     {0x00U,0x1CU,0x22U,0x41U,0x00U},{0x00U,0x41U,0x22U,0x1CU,0x00U},{0x14U,0x08U,0x3EU,0x08U,0x14U},{0x08U,0x08U,0x3EU,0x08U,0x08U},
220     /*             ,                               -                               .                               /             */
221     {0x00U,0x50U,0x30U,0x00U,0x00U},{0x08U,0x08U,0x08U,0x08U,0x08U},{0x00U,0x60U,0x60U,0x00U,0x00U},{0x20U,0x10U,0x08U,0x04U,0x02U},
222     /*             0                               1                               2                               3             */
223     {0x3EU,0x51U,0x49U,0x45U,0x3EU},{0x00U,0x42U,0x7FU,0x40U,0x00U},{0x42U,0x61U,0x51U,0x49U,0x46U},{0x21U,0x41U,0x45U,0x4BU,0x31U},
224     /*             4                               5                               6                               7             */
225     {0x18U,0x14U,0x12U,0x7FU,0x10U},{0x27U,0x45U,0x45U,0x45U,0x39U},{0x3CU,0x4AU,0x49U,0x49U,0x30U},{0x01U,0x71U,0x09U,0x05U,0x03U},
226     /*             8                               9                               :                               ;             */
227     {0x36U,0x49U,0x49U,0x49U,0x36U},{0x06U,0x49U,0x49U,0x29U,0x1EU},{0x00U,0x36U,0x36U,0x00U,0x00U},{0x00U,0x56U,0x36U,0x00U,0x00U},
228     /*             <                               =                               >                               ?             */
229     {0x08U,0x14U,0x22U,0x41U,0x00U},{0x14U,0x14U,0x14U,0x14U,0x14U},{0x00U,0x41U,0x22U,0x14U,0x08U},{0x02U,0x01U,0x51U,0x09U,0x06U},
230     /*             @                               A                               B                               C             */
231     {0x32U,0x49U,0x79U,0x41U,0x3EU},{0x7EU,0x11U,0x11U,0x11U,0x7EU},{0x7FU,0x49U,0x49U,0x49U,0x36U},{0x3EU,0x41U,0x41U,0x41U,0x22U},
232     /*             D                               E                               F                               G             */
233     {0x7FU,0x41U,0x41U,0x22U,0x1CU},{0x7FU,0x49U,0x49U,0x49U,0x41U},{0x7FU,0x09U,0x09U,0x09U,0x01U},{0x3EU,0x41U,0x49U,0x49U,0x3AU},
234     /*             H                               I                               J                               K             */
235     {0x7FU,0x08U,0x08U,0x08U,0x7FU},{0x00U,0x41U,0x7FU,0x41U,0x00U},{0x20U,0x40U,0x41U,0x3FU,0x01U},{0x7FU,0x08U,0x14U,0x22U,0x41U},
236     /*             L                               M                               N                               O             */
237     {0x7FU,0x40U,0x40U,0x40U,0x40U},{0x7FU,0x02U,0x0CU,0x02U,0x7FU},{0x7FU,0x04U,0x08U,0x10U,0x7FU},{0x3EU,0x41U,0x41U,0x41U,0x3EU},
238     /*             P                               Q                               R                               S             */
239     {0x7FU,0x09U,0x09U,0x09U,0x06U},{0x3EU,0x41U,0x51U,0x21U,0x5EU},{0x7FU,0x09U,0x19U,0x29U,0x46U},{0x46U,0x49U,0x49U,0x49U,0x31U},
240     /*             T                               U                               V                               W             */
241     {0x01U,0x01U,0x7FU,0x01U,0x01U},{0x3FU,0x40U,0x40U,0x40U,0x3FU},{0x1FU,0x20U,0x40U,0x20U,0x1FU},{0x3FU,0x40U,0x38U,0x40U,0x3FU},
242     /*             X                               Y                               Z                               [             */
243     {0x63U,0x14U,0x08U,0x14U,0x63U},{0x07U,0x08U,0x70U,0x08U,0x07U},{0x61U,0x51U,0x49U,0x45U,0x43U},{0x00U,0x7FU,0x41U,0x41U,0x00U},
244     /*             \                               ]                               ^                               _             */
245     {0x15U,0x16U,0x7CU,0x16U,0x15U},{0x00U,0x41U,0x41U,0x7FU,0x00U},{0x04U,0x02U,0x01U,0x02U,0x04U},{0x40U,0x40U,0x40U,0x40U,0x40U},
246     /*             `                               a                               b                               c             */
247     {0x00U,0x01U,0x02U,0x04U,0x00U},{0x20U,0x54U,0x54U,0x54U,0x78U},{0x7FU,0x48U,0x44U,0x44U,0x38U},{0x38U,0x44U,0x44U,0x44U,0x40U},
248     /*             d                               e                               f                               g             */
249     {0x38U,0x44U,0x44U,0x48U,0x7FU},{0x38U,0x54U,0x54U,0x54U,0x18U},{0x08U,0x7EU,0x09U,0x01U,0x02U},{0x0CU,0x52U,0x52U,0x52U,0x3EU},
250     /*             h                               i                               j                               k             */
251     {0x7FU,0x08U,0x04U,0x04U,0x78U},{0x00U,0x44U,0x7DU,0x40U,0x00U},{0x20U,0x40U,0x40U,0x3DU,0x00U},{0x7FU,0x10U,0x28U,0x44U,0x00U},
252     /*             l                               m                               n                               o             */
253     {0x00U,0x41U,0x7FU,0x40U,0x00U},{0x7CU,0x04U,0x18U,0x04U,0x78U},{0x7CU,0x08U,0x04U,0x04U,0x78U},{0x38U,0x44U,0x44U,0x44U,0x38U},
254     /*             p                               q                               r                               s             */
255     {0x7CU,0x14U,0x14U,0x14U,0x08U},{0x08U,0x14U,0x14U,0x18U,0x7CU},{0x7CU,0x08U,0x04U,0x04U,0x08U},{0x48U,0x54U,0x54U,0x54U,0x20U},
256     /*             t                               u                               v                               w             */
257     {0x04U,0x3FU,0x44U,0x40U,0x20U},{0x3CU,0x40U,0x40U,0x20U,0x7CU},{0x1CU,0x20U,0x40U,0x20U,0x1CU},{0x3CU,0x40U,0x30U,0x40U,0x3CU},
258     /*             x                               y                               z                               {             */
259     {0x44U,0x28U,0x10U,0x28U,0x44U},{0x0CU,0x50U,0x50U,0x50U,0x3CU},{0x44U,0x64U,0x54U,0x4CU,0x44U},{0x00U,0x08U,0x36U,0x41U,0x00U},
260     /*             |                               }                               ~             */
261     {0x00U,0x00U,0x7FU,0x00U,0x00U},{0x00U,0x41U,0x36U,0x08U,0x00U},{0x08U,0x04U,0x08U,0x10U,0x08U}
262 };
263 
264 const cy_stc_seglcd_font_t cy_segLCD_5x8DmFont =
265 {
266     .first   = ' ',
267     .last    = '~',
268     .ascii   = true,
269     .fontMap = (uint8_t*)fontMap5x8
270 };
271 
272 
273 /*******************************************************************************
274 * Function Name: GetDataRegPtr
275 ****************************************************************************//**
276 *
277 * Returns a pointer to the data frame register for a specified pixel.
278 * Used by \ref Cy_SegLCD_WritePixel and \ref Cy_SegLCD_ReadPixel functions.
279 *
280 * \param base  The base pointer to the LCD instance registers.
281 * \param pixel The predefined packed number that points to the pixel location
282 *              in the frame buffer.
283 *
284 *******************************************************************************/
GetDataRegPtr(LCD_Type * base,uint32_t pixel)285 static volatile uint32_t * GetDataRegPtr(LCD_Type * base, uint32_t pixel)
286 {
287     volatile uint32_t * locDataPtr[] = {LCD_DATA0(base), LCD_DATA1(base), LCD_DATA2(base), LCD_DATA3(base)};
288 
289     return (&(locDataPtr[CY_SEGLCD_EXTR_COM(pixel) / CY_SEGLCD_NIBBLE][CY_SEGLCD_EXTR_OCT(pixel)]));
290 }
291 
292 
293 /*******************************************************************************
294 * Function Name: InvClrData
295 ****************************************************************************//**
296 *
297 * Inverts or clears the Frame Data buffer.
298 * Used by \ref Cy_SegLCD_Deinit,
299 *         \ref Cy_SegLCD_ClrFrame and
300 *         \ref Cy_SegLCD_InvFrame functions.
301 *
302 * \param base  The base pointer to the LCD instance registers.
303 * \param inv:
304 *    - true - inverts the data buffer,
305 *    - false - clears the data buffer.
306 *
307 *******************************************************************************/
InvClrData(LCD_Type * base,bool inv)308 static void InvClrData(LCD_Type * base, bool inv)
309 {
310     uint32_t i;
311 
312     for (i = 0UL; i < LCD_NUMPORTS; i++)
313     {
314         LCD_DATA0(base)[i] = (inv) ? (~LCD_DATA0(base)[i]) : 0UL;
315 
316         #if (0UL != LCD_NUMPORTS8)
317             LCD_DATA1(base)[i] = (inv) ? (~LCD_DATA1(base)[i]) : 0UL;
318 
319             #if (0UL != LCD_NUMPORTS16)
320                 LCD_DATA2(base)[i] = (inv) ? (~LCD_DATA2(base)[i]) : 0UL;
321                 LCD_DATA3(base)[i] = (inv) ? (~LCD_DATA3(base)[i]) : 0UL;
322             #endif /* LCD_NUMPORTS16 */
323         #endif /* LCD_NUMPORTS8 */
324     }
325 }
326 
327 
328 /*******************************************************************************
329 * Function Name: NumToChar
330 ****************************************************************************//**
331 *
332 * Converts an one-digit hexadecimal numbers 0x0...0xF
333 * into the ASCII character codes.
334 * Used by the \ref Cy_SegLCD_WriteNumber function.
335 *
336 * \param value The value to be converted.
337 * \return The ASCII code of the 'value' character.
338 *
339 *******************************************************************************/
NumToChar(uint32_t value)340 static char_t NumToChar(uint32_t value)
341 {
342     uint32_t character;
343 
344     if (value < 10UL) /* For dec numbers 0...9 */
345     {
346         character = (uint32_t)'0' + value;
347     }
348     else if (value < 0x10UL) /* For hex numbers A...F */
349     {
350         character = ((uint32_t)'A' - 0xAUL) + value;
351     }
352     else
353     {
354         character = (uint32_t)' '; /* The blank/space character */
355     }
356 
357     return ((char_t)character);
358 }
359 
360 
361 /*******************************************************************************
362 * Function Name: Cy_SegLCD_Init
363 ****************************************************************************//**
364 *
365 * Initializes/restores the default Segment LCD block configuration.
366 *
367 * \param base   The base pointer to the LCD instance registers.
368 * \param config The pointer to a configuration structure.
369 * \return \ref cy_en_seglcd_status_t.
370 *
371 * Side Effects: The block is disabled to change the settings.
372 *
373 * \funcusage
374 * \snippet seglcd/snippet/SegLCD_Snpt.c snippet_Cy_SegLCD_Config
375 * \snippet seglcd/snippet/SegLCD_Snpt.c snippet_Cy_SegLCD_Init
376 *
377 *******************************************************************************/
Cy_SegLCD_Init(LCD_Type * base,cy_stc_seglcd_config_t const * config)378 cy_en_seglcd_status_t Cy_SegLCD_Init(LCD_Type * base, cy_stc_seglcd_config_t const * config)
379 {
380     cy_en_seglcd_status_t retVal = CY_SEGLCD_BAD_PARAM;
381 
382     if (NULL != base)
383     {
384         CY_ASSERT_L3(CY_SEGLCD_IS_SPEED_VALID(config->speed));
385         CY_ASSERT_L3(CY_SEGLCD_IS_WAVE_VALID (config->wave));
386         CY_ASSERT_L3(CY_SEGLCD_IS_DRIVE_VALID(config->drive));
387         CY_ASSERT_L3(CY_SEGLCD_IS_BIAS_VALID (base, config->bias, config->speed));
388         CY_ASSERT_L2(CY_SEGLCD_IS_LSCLK_VALID (config->lsClk));
389         CY_ASSERT_L1(CY_SEGLCD_IS_COM_NUM_VALID(config->comNum));
390         CY_ASSERT_L2(CY_SEGLCD_IS_RATE_VALID (config->frRate));
391         CY_ASSERT_L2(CY_SEGLCD_IS_CNTR_VALID (config->contrast));
392         CY_ASSERT_L2(CY_SEGLCD_IS_FREQ_VALID (config->clkFreq));
393 
394         uint32_t locCheck = ((CY_SEGLCD_SPEED_LOW == config->speed) && (CY_SEGLCD_REV_1(base))) ? (CY_SEGLCD_DIV_MAX_LS_VER1) : (CY_SEGLCD_DIV_MAX);
395         uint32_t locSubfr = CY_SYSLIB_DIV_ROUND((CY_SYSLIB_DIV_ROUND(config->clkFreq, config->frRate * 4UL * config->comNum) - 1UL) * config->contrast, 100UL);
396         uint32_t locDead = CY_SYSLIB_DIV_ROUND(CY_SYSLIB_DIV_ROUND(config->clkFreq * ((uint32_t)(100UL - (uint32_t)config->contrast)), (uint32_t)config->frRate), 100UL);
397 
398         if ((locSubfr <= locCheck) && (locDead <= locCheck))
399         {
400             uint32_t locLsClk = (uint32_t)((CY_SEGLCD_REV_1(base)) ? CY_SEGLCD_LSCLK_LF : config->lsClk);
401 
402             Cy_SegLCD_Disable(base);
403 
404             /* Calculate the sub-frame and dead-time dividers */
405             LCD_DIVIDER(base) = _VAL2FLD(LCD_DIVIDER_SUBFR_DIV, locSubfr) |
406                                 _VAL2FLD(LCD_DIVIDER_DEAD_DIV,  locDead);
407 
408             /* Set the rest of settings */
409             LCD_CONTROL(base) = _VAL2FLD(LCD_CONTROL_LCD_MODE, config->speed) |
410                                 _VAL2FLD(LCD_CONTROL_TYPE,     config->wave)  |
411                                 _VAL2FLD(LCD_CONTROL_OP_MODE,  config->drive) |
412                                 _VAL2FLD(LCD_CONTROL_BIAS,     config->bias)  |
413                         _VAL2FLD(LCD_V2_CONTROL_CLOCK_LS_SEL,  locLsClk)      |
414             /* Convert the comNum from the user range (2-16) into the machine range (0-14). */
415                                 _VAL2FLD(LCD_CONTROL_COM_NUM,  config->comNum - 2UL);
416 
417             retVal = CY_SEGLCD_SUCCESS;
418         }
419     }
420 
421     return (retVal);
422 }
423 
424 
425 /*******************************************************************************
426 * Function Name: Cy_SegLCD_Contrast
427 ****************************************************************************//**
428 *
429 * Sets a specified contrast.
430 *
431 * \param base   The base pointer to the LCD instance registers.
432 * \param contrast The contrast value to be set.
433 * \param config The pointer to a configuration structure.
434 * \return \ref cy_en_seglcd_status_t.
435 *
436 * Side Effects: The configuration structure contrast value is also updated.
437 *
438 * \funcusage
439 * \snippet seglcd/snippet/SegLCD_Snpt.c snippet_Cy_SegLCD_ContrastInit
440 * \snippet seglcd/snippet/SegLCD_Snpt.c snippet_Cy_SegLCD_Contrast
441 *
442 *******************************************************************************/
Cy_SegLCD_Contrast(LCD_Type * base,uint32_t contrast,cy_stc_seglcd_config_t * config)443 cy_en_seglcd_status_t Cy_SegLCD_Contrast(LCD_Type * base, uint32_t contrast, cy_stc_seglcd_config_t * config)
444 {
445     cy_en_seglcd_status_t retVal = CY_SEGLCD_BAD_PARAM;
446 
447     if (CY_SEGLCD_IS_CNTR_VALID (contrast))
448     {
449         bool enabled = CY_SEGLCD_IS_ENABLED(base); /* Store the block state */
450 
451         config->contrast = (uint8_t)contrast;
452 
453         retVal = Cy_SegLCD_Init(base, config);
454 
455         if ((CY_SEGLCD_SUCCESS == retVal) && enabled)
456         {
457             Cy_SegLCD_Enable(base); /* Restore the block state */
458         }
459     }
460 
461     return (retVal);
462 }
463 
464 
465 /*******************************************************************************
466 * Function Name: Cy_SegLCD_Deinit
467 ****************************************************************************//**
468 *
469 * De-initializes the LCD block (resets the block registers to default state).
470 *
471 * \param base   The base pointer to the LCD instance registers.
472 *
473 * \funcusage
474 * \snippet seglcd/snippet/SegLCD_Snpt.c snippet_Cy_SegLCD_Deinit
475 *
476 *******************************************************************************/
Cy_SegLCD_Deinit(LCD_Type * base)477 void Cy_SegLCD_Deinit(LCD_Type * base)
478 {
479     Cy_SegLCD_Disable(base);
480 
481     LCD_CONTROL(base) = 0UL;
482     LCD_DIVIDER(base) = 0UL;
483 
484     InvClrData(base, false); /* Clear the entire frame buffer to all zeroes */
485 }
486 
487 
488 /*******************************************************************************
489 * Function Name: Cy_SegLCD_Enable
490 ****************************************************************************//**
491 *
492 * Enables the Segment LCD block.
493 *
494 * \param base The base pointer to the LCD instance registers.
495 *
496 * \funcusage
497 * \snippet seglcd/snippet/SegLCD_Snpt.c snippet_Cy_SegLCD_Config
498 * \snippet seglcd/snippet/SegLCD_Snpt.c snippet_Cy_SegLCD_Init
499 *
500 *******************************************************************************/
Cy_SegLCD_Enable(LCD_Type * base)501 void Cy_SegLCD_Enable(LCD_Type * base)
502 {
503     if (_FLD2BOOL(LCD_CONTROL_LCD_MODE, LCD_CONTROL(base)))
504     {
505         LCD_CONTROL(base) |= LCD_CONTROL_HS_EN_Msk;
506     }
507     else /* CY_SEGLCD_SPEED_HIGH */
508     {
509         uint32_t timeout;
510 
511         LCD_CONTROL(base) |= LCD_CONTROL_LS_EN_Msk;
512 
513         for (timeout = CY_SEGLCD_TIMEOUT; (_FLD2BOOL(LCD_CONTROL_LS_EN_STAT, LCD_CONTROL(base))) && (0UL != timeout); timeout--)
514         {
515             /* Waiting for enabling takes effect in the ILO clock domain.
516              * The timeout status does not affect anything,
517              * the timeout is to avoid a deadlock here.
518              */
519             Cy_SysLib_DelayUs(1U);
520         }
521     }
522 }
523 
524 
525 /*******************************************************************************
526 * Function Name: Cy_SegLCD_Disable
527 ****************************************************************************//**
528 *
529 * Disables the Segment LCD block.
530 *
531 * \param base The base pointer to the LCD instance registers.
532 *
533 * \funcusage
534 * \snippet seglcd/snippet/SegLCD_Snpt.c snippet_Cy_SegLCD_Disable
535 *
536 *******************************************************************************/
Cy_SegLCD_Disable(LCD_Type * base)537 void Cy_SegLCD_Disable(LCD_Type * base)
538 {
539     if (_FLD2BOOL(LCD_CONTROL_LCD_MODE, LCD_CONTROL(base))) /* CY_SEGLCD_SPEED_HIGH */
540     {
541         LCD_CONTROL(base) &= ~LCD_CONTROL_HS_EN_Msk;
542     }
543     else /* CY_SEGLCD_SPEED_LOW */
544     {
545         if (_FLD2BOOL(LCD_CONTROL_LS_EN, LCD_CONTROL(base)))
546         {
547             uint32_t timeout;
548 
549             for (timeout = CY_SEGLCD_TIMEOUT; (!_FLD2BOOL(LCD_CONTROL_LS_EN_STAT, LCD_CONTROL(base))) && (0UL != timeout); timeout--)
550             {
551                  Cy_SysLib_DelayUs(1U); /* Waiting for enabling takes effect in the ILO clock domain. */
552             }
553 
554             LCD_CONTROL(base) &= ~LCD_CONTROL_LS_EN_Msk;
555 
556             for (timeout = CY_SEGLCD_TIMEOUT; (_FLD2BOOL(LCD_CONTROL_LS_EN_STAT, LCD_CONTROL(base))) && (0UL != timeout); timeout--)
557             {
558                 Cy_SysLib_DelayUs(1U); /* Waiting for disabling takes effect in the ILO clock domain. */
559             }
560 
561             /* The timeout status does not affect anything, the timeout is to avoid a deadlock */
562         }
563     }
564 }
565 
566 
567 /*******************************************************************************
568 * Function Name: Cy_SegLCD_ClrFrame
569 ****************************************************************************//**
570 *
571 * Clears the frame buffer and initiates the common lines.
572 * In general case it is recommended to be called after \ref Cy_SegLCD_Init
573 *                                           and before \ref Cy_SegLCD_Enable.
574 *
575 * \param base    The base pointer to the LCD instance registers.
576 * \param commons The pointer to array of common lines.
577 *                The array size is specified by \ref cy_stc_seglcd_config_t.comNum.
578 *                Each common line value should be made using
579 *                \ref CY_SEGLCD_COMMON macro.
580 *
581 * \return \ref cy_en_seglcd_status_t.
582 *
583 * \funcusage
584 * \snippet seglcd/snippet/SegLCD_Snpt.c snippet_Cy_SegLCD_Config
585 * \snippet seglcd/snippet/SegLCD_Snpt.c snippet_Cy_SegLCD_Init
586 *
587 *******************************************************************************/
Cy_SegLCD_ClrFrame(LCD_Type * base,uint32_t const * commons)588 cy_en_seglcd_status_t Cy_SegLCD_ClrFrame(LCD_Type * base, uint32_t const * commons)
589 {
590     uint32_t retVal = (uint32_t)CY_SEGLCD_BAD_PARAM;
591 
592     if (NULL != commons)
593     {
594         uint32_t i;
595 
596         InvClrData(base, false); /* Clear the entire frame buffer to all zeroes */
597 
598         retVal = (uint32_t)CY_SEGLCD_SUCCESS;
599 
600         /* Re-initialize the commons */
601         for (i = 0UL; i < CY_SEGLCD_COM_NUM(base); i++)
602         {
603             retVal |= (uint32_t)Cy_SegLCD_WritePixel(base, commons[i], true);
604         }
605     }
606 
607     return((cy_en_seglcd_status_t)retVal);
608 }
609 
610 
611 /*******************************************************************************
612 * Function Name: Cy_SegLCD_InvFrame
613 ****************************************************************************//**
614 *
615 * Inverts the frame buffer (all the connected pixel states are inverted).
616 *
617 * \param base    The base pointer to the LCD instance registers.
618 * \param commons The pointer to an array of common lines.
619 *                The array size is specified by \ref cy_stc_seglcd_config_t.comNum.
620 *                Each common line value should be made using
621 *                \ref CY_SEGLCD_COMMON macro.
622 *
623 * \return \ref cy_en_seglcd_status_t.
624 *
625 * \funcusage
626 * \snippet seglcd/snippet/SegLCD_Snpt.c snippet_Cy_SegLCD_InvFrame
627 *
628 *******************************************************************************/
Cy_SegLCD_InvFrame(LCD_Type * base,uint32_t const * commons)629 cy_en_seglcd_status_t Cy_SegLCD_InvFrame(LCD_Type * base, uint32_t const * commons)
630 {
631     uint32_t retVal = (uint32_t)CY_SEGLCD_BAD_PARAM;
632 
633     if (NULL != commons)
634     {
635         uint32_t i;
636 
637         InvClrData(base, true); /* Invert the entire frame buffer. */
638 
639         retVal = (uint32_t)CY_SEGLCD_SUCCESS;
640 
641         /* Re-initialize the common lines */
642         for (i = 0UL; i < CY_SEGLCD_COM_NUM(base); i++)
643         {
644             uint32_t locCom = commons[i] & ~CY_SEGLCD_COM_Msk;
645             uint32_t j = 0UL;
646 
647             /* Clear common lines data after frame buffer inverting */
648             for (j = 0UL; j < CY_SEGLCD_COM_NUM(base); j++)
649             {
650                 retVal |= (uint32_t)Cy_SegLCD_WritePixel(base, locCom | ((uint32_t)(j << CY_SEGLCD_COM_Pos)), false);
651             }
652 
653             /* Set data for the common lines */
654             retVal |= (uint32_t)Cy_SegLCD_WritePixel(base, commons[i], true);
655         }
656     }
657 
658     return((cy_en_seglcd_status_t)retVal);
659 }
660 
661 
662 /*******************************************************************************
663 * Function Name: Cy_SegLCD_WritePixel
664 ****************************************************************************//**
665 *
666 *  Sets or clears a specified pixel.
667 *
668 * \param base The base pointer to the LCD instance registers.
669 * \param pixel The predefined packed number that points to the pixel location
670 *              in the frame buffer.
671 * \param value Specifies the pixel on/off state.
672 * \return \ref cy_en_seglcd_status_t.
673 *
674 * \funcusage
675 * \snippet seglcd/snippet/SegLCD_Snpt.h snippet_Cy_SegLCD_DefPixel
676 * \snippet seglcd/snippet/SegLCD_Snpt.c snippet_Cy_SegLCD_ActPixel
677 *
678 *******************************************************************************/
Cy_SegLCD_WritePixel(LCD_Type * base,uint32_t pixel,bool value)679 cy_en_seglcd_status_t Cy_SegLCD_WritePixel(LCD_Type * base, uint32_t pixel, bool value)
680 {
681     cy_en_seglcd_status_t retVal = CY_SEGLCD_BAD_PIXEL;
682 
683     if (CY_SEGLCD_IS_PIX_VALID(pixel))
684     {
685         /* Extract the pixel location. */
686         uint32_t loc_Pos = CY_SEGLCD_PIX_Pos(pixel);
687         uint32_t loc_Msk = CY_SEGLCD_PIX_Msk(pixel);
688 
689         /* Write a new pixel value into the frame buffer. */
690         CY_REG32_CLR_SET(*GetDataRegPtr(base, pixel), loc, value ? 1UL : 0UL);
691 
692         retVal = CY_SEGLCD_SUCCESS;
693     }
694 
695     return(retVal);
696 }
697 
698 
699 /*******************************************************************************
700 * Function Name: Cy_SegLCD_ReadPixel
701 ****************************************************************************//**
702 *
703 * Gets the state of a specified pixel.
704 *
705 * \param base The base pointer to the LCD instance registers.
706 * \param pixel The predefined packed number that points to the pixel location
707 *              in the frame buffer. Each pixel value should be made using
708 *              \ref CY_SEGLCD_PIXEL macro.
709 * \return Boolean pixel state.
710 *         If pixel value is invalid - the 'false' is returned.
711 *
712 * \funcusage
713 * \snippet seglcd/snippet/SegLCD_Snpt.h snippet_Cy_SegLCD_DefPixel
714 * \snippet seglcd/snippet/SegLCD_Snpt.c snippet_Cy_SegLCD_ActPixel
715 *
716 *******************************************************************************/
Cy_SegLCD_ReadPixel(LCD_Type * base,uint32_t pixel)717 bool Cy_SegLCD_ReadPixel(LCD_Type * base, uint32_t pixel)
718 {
719     bool retVal = false;
720 
721     if (CY_SEGLCD_IS_PIX_VALID(pixel))
722     {
723         /* Get the pixel value from the frame buffer */
724         retVal = (0UL != (*GetDataRegPtr(base, pixel) & CY_SEGLCD_PIX_Msk(pixel)));
725     }
726     else
727     {
728         CY_ASSERT_L1(false);
729     }
730 
731     return (retVal);
732 }
733 
734 
735 /*******************************************************************************
736 * Function Name: Cy_SegLCD_WriteChar
737 ****************************************************************************//**
738 *
739 * Writes a specified character onto a specified display.
740 * Supports all display types except \ref CY_SEGLCD_BAR.
741 *
742 * \param base The base pointer to the LCD instance registers.
743 * \param character The code of the character to display.
744 *                  Should be within the font symbol codes range specified by
745 *           \ref cy_stc_seglcd_font_t.first and \ref cy_stc_seglcd_font_t.last
746 * \param position The position of the character/digit on display.
747 *                 Zero is the most left character/digit of the specified
748 *                 display \ref cy_stc_seglcd_disp_t.
749 * \param display The pointer to the display structure \ref cy_stc_seglcd_disp_t.
750 * \return \ref cy_en_seglcd_status_t.
751 *
752 * \funcusage
753 * \snippet seglcd/snippet/SegLCD_Snpt.c snippet_Cy_SegLCD_Char
754 *
755 *******************************************************************************/
Cy_SegLCD_WriteChar(LCD_Type * base,char_t character,uint32_t position,cy_stc_seglcd_disp_t const * display)756 cy_en_seglcd_status_t Cy_SegLCD_WriteChar(LCD_Type * base,
757                                             char_t   character,
758                                           uint32_t   position,
759                         cy_stc_seglcd_disp_t const * display)
760 {
761     uint32_t retVal = (uint32_t)CY_SEGLCD_BAD_PARAM;
762 
763     if (CY_SEGLCD_IS_SYMBOLIC(display, position)) /* If the display is symbolic/numeric */
764     {
765         uint32_t i;
766         uint32_t locChar = (uint32_t)character;
767         retVal = CY_SEGLCD_IS_BASIC(display->type) ? (uint32_t)CY_SEGLCD_SUCCESS : (uint32_t)CY_SEGLCD_CUSTOM;
768 
769         if ((character < display->font->first) || (character > display->font->last)) /* if out of the font range */
770         {
771             retVal |= (uint32_t)CY_SEGLCD_BAD_CHAR;
772             locChar = (uint32_t)CY_SEGLCD_SPACE(display); /* The blank (space) character */
773         }
774 
775         locChar = (uint32_t)(locChar - (uint32_t)display->font->first); /* Shift to the font char map starting index */
776 
777         for (i = 0UL; i < (uint32_t)display->type; i++)
778         {
779             uint32_t locPix = *(display->pixMap + (position * (uint32_t)display->type) + i); /* Current display pixel */
780             uint32_t locIdx = _FLD2VAL(CY_SEGLCD_SYM_BYTE_IDX, i) + (locChar * CY_SYSLIB_DIV_ROUNDUP((uint32_t)display->type, CY_SEGLCD_OCTET)); /* current symbol byte index */
781             bool     locVal = 0U != (display->font->fontMap[locIdx] & (uint8_t)(1U << _FLD2VAL(CY_SEGLCD_SYM_BIT_IDX, i))); /* current pixel value */
782 
783             retVal |= (uint32_t)Cy_SegLCD_WritePixel(base, locPix, display->invert != locVal);
784         }
785     }
786 
787     return((cy_en_seglcd_status_t)retVal);
788 }
789 
790 
791 /*******************************************************************************
792 * Function Name: Cy_SegLCD_WriteNumber
793 ****************************************************************************//**
794 *
795 * Displays an integer value onto a specified display.
796 * Supports all display types except \ref CY_SEGLCD_BAR.
797 *
798 * \note The sign conversion, sign display, decimal points, and other special segments
799 *       outside the display symbols themselves should be handled on upper layer code.
800 *
801 * \param base The base pointer to the LCD instance registers.
802 * \param value The unsigned integer number to be displayed.
803 * \param position The position of the least significant digit of the number
804 *        as counted left to right starting at 0 - the first symbol on the left
805 *        of the specified display.
806 *        If the specified display contains fewer symbols than the number
807 *        requires to be displayed, the extra (more significant) digit(s) is(are) not
808 *        displayed and the \ref CY_SEGLCD_EXCEED value is returned.
809 * \param display The pointer to the display structure \ref cy_stc_seglcd_disp_t.
810 * \param zeroes:
811 *    - true - all the unused digits on the left of the displayed value are zeroes.
812 *    - false - all the above mentioned digits are blank.
813 * \param hex:
814 *    - true - the value is displayed in the hexadecimal format.
815 *    - false - the value is displayed in the decimal format.
816 * \return \ref cy_en_seglcd_status_t.
817 *
818 * \funcusage
819 * \snippet seglcd/snippet/SegLCD_Snpt.c snippet_Cy_SegLCD_DecNum
820 * \snippet seglcd/snippet/SegLCD_Snpt.c snippet_Cy_SegLCD_HexNum
821 *
822 *******************************************************************************/
Cy_SegLCD_WriteNumber(LCD_Type * base,uint32_t value,uint32_t position,cy_stc_seglcd_disp_t const * display,bool zeroes,bool hex)823 cy_en_seglcd_status_t Cy_SegLCD_WriteNumber(LCD_Type * base,
824                                             uint32_t   value,
825                                             uint32_t   position,
826                           cy_stc_seglcd_disp_t const * display,
827                                                 bool   zeroes,
828                                                 bool   hex)
829 {
830     uint32_t retVal = (uint32_t)CY_SEGLCD_BAD_PARAM;
831 
832     if (CY_SEGLCD_IS_SYMBOLIC(display, position)) /* If the display is symbolic/numeric */
833     {
834         uint32_t locNum;
835         uint32_t i = position + 1UL;
836         uint32_t locDiv = (hex) ? 0x10UL : 10UL; /* The digit weight for hex/dec counting systems */
837         retVal = (uint32_t)CY_SEGLCD_SUCCESS;
838 
839         do
840         {
841             i--;
842 
843             if ((0UL == value) && (i != position) && (!zeroes))
844             {
845                 /* For 'not zeroes' mode each extra digit is cleared. */
846                 locNum = (uint32_t)CY_SEGLCD_NUM_BLANK;
847             }
848             else
849             {
850                 /* Display the subsequent digit or '0' for 'zeroes' mode */
851                 locNum = value % locDiv;
852             }
853 
854             /* Calculate the next digit value */
855             value = value / locDiv;
856 
857             retVal |= (uint32_t)Cy_SegLCD_WriteChar(base, (display->font->ascii) ? NumToChar(locNum) : (char_t)locNum, i, display);
858         }
859         while (i != 0UL); /* While the current digit position is in the range of the display, keep processing the output */
860 
861         if (0UL != value)
862         {
863             retVal |= (uint32_t)CY_SEGLCD_EXCEED;
864         }
865     }
866 
867     return((cy_en_seglcd_status_t)retVal);
868 }
869 
870 
871 /*******************************************************************************
872 * Function Name: Cy_SegLCD_WriteString
873 ****************************************************************************//**
874 *
875 * Writes a specified zero-terminated char string onto a specified display.
876 * Supports all display types except \ref CY_SEGLCD_BAR.
877 *
878 * \param base The base pointer to the LCD instance registers.
879 * \param string The pointer to the ASCII-coded null-terminated character string.
880 * \param position The position of the first string character at the display
881 *        as counted left to right starting at 0 - the first symbol on the left
882 *        of the specified display.
883 *        If the specified display contains fewer symbols than the string
884 *        requires to be displayed, the extra character(s) is(are) not displayed
885 *        and the \ref CY_SEGLCD_EXCEED value is returned.
886 * \param display The pointer to the display structure \ref cy_stc_seglcd_disp_t.
887 * \return \ref cy_en_seglcd_status_t.
888 *
889 * \funcusage
890 * \snippet seglcd/snippet/SegLCD_Snpt.c snippet_Cy_SegLCD_String
891 *
892 *******************************************************************************/
Cy_SegLCD_WriteString(LCD_Type * base,char_t const * string,uint32_t position,cy_stc_seglcd_disp_t const * display)893 cy_en_seglcd_status_t Cy_SegLCD_WriteString(LCD_Type * base,
894                                         char_t const * string,
895                                             uint32_t   position,
896                           cy_stc_seglcd_disp_t const * display)
897 {
898     uint32_t retVal = (uint32_t)CY_SEGLCD_BAD_PARAM;
899 
900     if (CY_SEGLCD_IS_ASCII(display, position)) /* If the display is symbolic/numeric and the font is ASCII-coded */
901     {
902         uint32_t i;
903         retVal = (uint32_t)CY_SEGLCD_SUCCESS;
904 
905         for (i = 0UL; (i + position) < display->symNum; i++)
906         {
907             retVal |= (uint32_t)Cy_SegLCD_WriteChar(base, ('\0' != string[i]) ? string[i] : CY_SEGLCD_SPACE(display), i + position, display);
908         }
909 
910         if ('\0' != string[i])
911         {
912             retVal |= (uint32_t)CY_SEGLCD_EXCEED;
913         }
914     }
915 
916     return((cy_en_seglcd_status_t)retVal);
917 }
918 
919 
920 /*******************************************************************************
921 * Function Name: Cy_SegLCD_BarGraph
922 ****************************************************************************//**
923 *
924 * Draws a bar onto a specified bar graph / dial display.
925 * Only the \ref CY_SEGLCD_BAR display type is supported.
926 *
927 * \param base The base pointer to the LCD instance registers.
928 * \param value The length of the bar in pixels.
929 * \param position The position of the first bar pixel as counted from the
930 *        beginning ('0' is the first pixel) of the specified display.
931 *        If the specified display contains fewer pixels than the bar
932 *        requires to be displayed, the extra pixel(s) is(are) not
933 *        displayed and the \ref CY_SEGLCD_EXCEED value is returned.
934 * \param display The pointer to the display structure \ref cy_stc_seglcd_disp_t.
935 * \return \ref cy_en_seglcd_status_t.
936 *
937 * \funcusage
938 * \snippet seglcd/snippet/SegLCD_Snpt.h snippet_Cy_SegLCD_BarLength
939 * \snippet seglcd/snippet/SegLCD_Snpt.c snippet_Cy_SegLCD_BarGraphDisplay
940 * \snippet seglcd/snippet/SegLCD_Snpt.c snippet_Cy_SegLCD_BarGraphValue
941 * \snippet seglcd/snippet/SegLCD_Snpt.c snippet_Cy_SegLCD_BarGraph
942 *
943 *******************************************************************************/
Cy_SegLCD_BarGraph(LCD_Type * base,uint32_t value,uint32_t position,cy_stc_seglcd_disp_t const * display)944 cy_en_seglcd_status_t Cy_SegLCD_BarGraph(LCD_Type * base,
945                                          uint32_t   value,
946                                          uint32_t   position,
947                        cy_stc_seglcd_disp_t const * display)
948 {
949     uint32_t retVal = (uint32_t)CY_SEGLCD_BAD_PARAM;
950 
951     if (CY_SEGLCD_IS_BARGRAPH(display, position)) /* If the display is bar graph / dial */
952     {
953         uint32_t i;
954         retVal = (uint32_t)CY_SEGLCD_SUCCESS;
955 
956         for (i = position; i < display->symNum; i++)
957         {
958             retVal |= (uint32_t)Cy_SegLCD_WritePixel(base, *(display->pixMap + i), i < (position + value));
959         }
960 
961         if (((uint32_t)CY_SEGLCD_BAD_PIXEL != retVal) && ((position + value) > display->symNum))
962         {
963             retVal |= (uint32_t)CY_SEGLCD_EXCEED;
964         }
965     }
966 
967     return((cy_en_seglcd_status_t)retVal);
968 }
969 CY_MISRA_BLOCK_END('MISRA C-2012 Rule 11.3')
970 
971 #endif /* CY_IP_MXLCD */
972 
973 /* [] END OF FILE */
974