2 * Copyright (c) 2020 Arm Limited. All rights reserved.
4 * SPDX-License-Identifier: Apache-2.0
6 * Licensed under the Apache License, Version 2.0 (the License); you may
7 * not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
14 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 * -----------------------------------------------------------------------------
21 * Title: Virtual I/O (VIO) implementation for
22 * Keil MCBSTM32F400 evaluation board
24 * -----------------------------------------------------------------------------
30 #include "cmsis_os2.h"
31 #include "cmsis_compiler.h"
32 #include "cmsis_vio.h"
34 #if !defined(CMSIS_VOUT)
35 #include "Board_LED.h" // ::Board Support:LED
36 #include "Board_GLCD.h" // ::Board Support:Graphic LCD
37 #include "GLCD_Config.h"
39 extern GLCD_FONT GLCD_Font_6x8;
40 extern GLCD_FONT GLCD_Font_16x24;
42 #if !defined(CMSIS_VIN)
43 #include "Board_Buttons.h" // ::Board Support:Buttons
46 // VIO input, output definitions
47 #define VIO_PRINT_MAX_SIZE 64U // maximum size of print memory
48 #define VIO_PRINT_MEM_NUM 4U // number of print memories
49 #define VIO_VALUE_NUM 3U // number of values
50 #define VIO_VALUE_XYZ_NUM 3U // number of XYZ values
51 #define VIO_IPV4_ADDRESS_NUM 2U // number of IPv4 addresses
52 #define VIO_IPV6_ADDRESS_NUM 2U // number of IPv6 addresses
54 // VIO input, output variables
55 __USED uint32_t vioSignalIn;
56 __USED uint32_t vioSignalOut;
57 __USED char vioPrintMem[VIO_PRINT_MEM_NUM][VIO_PRINT_MAX_SIZE];
58 __USED int32_t vioValue [VIO_VALUE_NUM];
59 __USED vioValueXYZ_t vioValueXYZ[VIO_VALUE_XYZ_NUM];
60 __USED vioAddrIPv4_t vioAddrIPv4[VIO_IPV4_ADDRESS_NUM];
61 __USED vioAddrIPv6_t vioAddrIPv6[VIO_IPV6_ADDRESS_NUM];
63 static uint32_t cursor_x; // GLCD cursor x (horizontal) position (in pixels)
64 static uint32_t cursor_y; // GLCD cursor y (vertical) position (in pixels)
65 static osMutexId_t mid_GLCD; // Mutex ID of GLCD mutex
67 // Initialize test input, output.
73 memset (vioPrintMem, 0, sizeof(vioPrintMem));
74 memset (vioValue, 0, sizeof(vioValue));
75 memset (vioValueXYZ, 0, sizeof(vioValueXYZ));
76 memset (vioAddrIPv4, 0, sizeof(vioAddrIPv4));
77 memset (vioAddrIPv6, 0, sizeof(vioAddrIPv6));
79 #if !defined(CMSIS_VOUT)
80 (void)LED_Initialize();
82 mid_GLCD = osMutexNew(NULL); // Create GLCD mutex
83 if (mid_GLCD != NULL) {
84 (void)GLCD_Initialize();
85 (void)GLCD_SetBackgroundColor(GLCD_COLOR_BLUE);
86 (void)GLCD_SetForegroundColor(GLCD_COLOR_WHITE);
87 (void)GLCD_ClearScreen();
91 #if !defined(CMSIS_VIN)
92 (void)Buttons_Initialize();
96 // Print formated string to test terminal.
97 int32_t vioPrint (uint32_t level, const char *format, ...) {
101 #if !defined(CMSIS_VOUT)
102 uint16_t cursor_x, cursor_y; // GLCD cursor position (in pixels)
103 uint8_t font_w, font_h;
108 if (level > vioLevelError) {
112 if (level > VIO_PRINT_MEM_NUM) {
116 va_start(args, format);
118 ret = vsnprintf((char *)vioPrintMem[level], sizeof(vioPrintMem[level]), format, args);
122 #if !defined(CMSIS_VOUT)
123 if (mid_GLCD != NULL) {
124 osMutexAcquire(mid_GLCD, osWaitForever);
126 case vioLevelNone: // Normal text
127 font_w = GLCD_Font_6x8.width;
128 font_h = GLCD_Font_6x8.height;
129 cursor_x = 0U; // Normal text starting position
130 cursor_y = 0U; // 1st text row
131 (void)GLCD_SetFont (&GLCD_Font_6x8);
132 (void)GLCD_SetForegroundColor (GLCD_COLOR_WHITE);
134 case vioLevelHeading: // Heading text
135 font_w = GLCD_Font_16x24.width;
136 font_h = GLCD_Font_16x24.height;
137 cursor_x = 0U; // Heading text starting position
138 cursor_y = font_h; // 2nd text row
139 (void)GLCD_SetFont (&GLCD_Font_16x24);
140 (void)GLCD_SetForegroundColor (GLCD_COLOR_GREEN);
142 case vioLevelMessage: // Message text
143 font_w = GLCD_Font_16x24.width;
144 font_h = GLCD_Font_16x24.height;
145 cursor_x = 0U; // Message text starting position
146 cursor_y = font_h * 5U; // 6th text row
147 (void)GLCD_SetFont (&GLCD_Font_16x24);
148 (void)GLCD_SetForegroundColor (GLCD_COLOR_WHITE);
150 case vioLevelError: // Error text
151 font_w = GLCD_Font_16x24.width;
152 font_h = GLCD_Font_16x24.height;
153 cursor_x = 0U; // Error text starting position
154 cursor_y = font_h * 9U; // 10th text row
155 (void)GLCD_SetFont (&GLCD_Font_16x24);
156 (void)GLCD_SetForegroundColor (GLCD_COLOR_RED);
161 while (vioPrintMem[level][i] != 0) {
162 ch = vioPrintMem[level][i];
166 case 0x0A: // Line Feed ('\n')
168 if (cursor_y >= GLCD_HEIGHT) {
169 // If cursor is out of screen vertically then rollover to vertical 0
173 case 0x0D: // Carriage Return ('\r')
174 // Move the cursor to horizontal 0
177 default: // Any other character
178 // Display current character at the cursor position
179 (void)GLCD_DrawChar(cursor_x, cursor_y, ch);
180 // Move the cursor to the next character on the right
182 if (cursor_x >= GLCD_WIDTH) {
183 // If cursor is out of screen horizontally then rollover to horizontal 0
187 if (cursor_y >= GLCD_HEIGHT) {
188 // If cursor is out of screen vertically then rollover to vertical 0
196 osMutexRelease(mid_GLCD);
203 // Set signal output.
204 void vioSetSignal (uint32_t mask, uint32_t signal) {
206 vioSignalOut &= ~mask;
207 vioSignalOut |= mask & signal;
209 #if !defined(CMSIS_VOUT)
210 (void)LED_SetOut(mask & signal);
215 uint32_t vioGetSignal (uint32_t mask) {
218 #if !defined(CMSIS_VIN)
219 vioSignalIn = Buttons_GetState();
221 signal = vioSignalIn;
223 return (signal & mask);
227 void vioSetValue (uint32_t id, int32_t value) {
230 if (index >= VIO_VALUE_NUM) {
231 return; /* return in case of out-of-range index */
234 vioValue[index] = value;
238 int32_t vioGetValue (uint32_t id) {
242 if (index >= VIO_VALUE_NUM) {
243 return value; /* return default in case of out-of-range index */
246 value = vioValue[index];
251 // Set XYZ value output.
252 void vioSetXYZ (uint32_t id, vioValueXYZ_t valueXYZ) {
255 if (index >= VIO_VALUE_XYZ_NUM) {
256 return; /* return in case of out-of-range index */
259 vioValueXYZ[index] = valueXYZ;
262 // Get XYZ value input.
263 vioValueXYZ_t vioGetXYZ (uint32_t id) {
265 vioValueXYZ_t valueXYZ = {0, 0, 0};
267 if (index >= VIO_VALUE_XYZ_NUM) {
268 return valueXYZ; /* return default in case of out-of-range index */
271 valueXYZ = vioValueXYZ[index];
276 // Set IPv4 address output.
277 void vioSetIPv4 (uint32_t id, vioAddrIPv4_t addrIPv4) {
280 if (index >= VIO_IPV4_ADDRESS_NUM) {
281 return; /* return in case of out-of-range index */
284 vioAddrIPv4[index] = addrIPv4;
287 // Get IPv4 address input.
288 vioAddrIPv4_t vioGetIPv4 (uint32_t id) {
290 vioAddrIPv4_t addrIPv4 = {0U, 0U, 0U, 0U};
292 if (index >= VIO_IPV4_ADDRESS_NUM) {
293 return addrIPv4; /* return default in case of out-of-range index */
296 addrIPv4 = vioAddrIPv4[index];
301 // Set IPv6 address output.
302 void vioSetIPv6 (uint32_t id, vioAddrIPv6_t addrIPv6) {
305 if (index >= VIO_IPV6_ADDRESS_NUM) {
306 return; /* return in case of out-of-range index */
309 vioAddrIPv6[index] = addrIPv6;
312 // Get IPv6 address input.
313 vioAddrIPv6_t vioGetIPv6 (uint32_t id) {
315 vioAddrIPv6_t addrIPv6 = {0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
316 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U};
318 if (index >= VIO_IPV6_ADDRESS_NUM) {
319 return addrIPv6; /* return default in case of out-of-range index */
322 addrIPv6 = vioAddrIPv6[index];