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