Arm-2D  
2D Image Processing Library for Cortex-M Processors
arm_2d_helper.h
1/*
2 * Copyright (C) 2022 Arm Limited or its affiliates. All rights reserved.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
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
9 *
10 * www.apache.org/licenses/LICENSE-2.0
11 *
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.
17 */
18
19/* ----------------------------------------------------------------------
20 * Project: Arm-2D Library
21 * Title: #include "arm_2d_helper.h"
22 * Description: Public header file for the all helper services
23 *
24 * $Date: 07. Sept 2024
25 * $Revision: V.2.0.0
26 *
27 * Target Processor: Cortex-M cores
28 * -------------------------------------------------------------------- */
29
30#ifndef __ARM_2D_HELPER_H__
31#define __ARM_2D_HELPER_H__
32
33/*============================ INCLUDES ======================================*/
34#include "arm_2d.h"
35#include "./__arm_2d_helper_common.h"
36#include "./arm_2d_helper_pfb.h"
37#include "./arm_2d_helper_scene.h"
38#include "./arm_2d_disp_adapters.h"
39#include "./arm_2d_helper_list.h"
40#include "./arm_2d_helper_shape.h"
41#include "./arm_2d_helper_font.h"
42#include "./arm_2d_helper_control.h"
43
44//#include "./arm_2d_helper_map.h"
45
46
47#include <stdlib.h>
48#include <assert.h>
49
50#ifdef __cplusplus
51extern "C" {
52#endif
53
54#if defined(__clang__)
55# pragma clang diagnostic push
56# pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
57# pragma clang diagnostic ignored "-Wunused-function"
58# pragma clang diagnostic ignored "-Wmissing-declarations"
59# pragma clang diagnostic ignored "-Wpadded"
60#elif defined(__IS_COMPILER_ARM_COMPILER_5__)
61# pragma diag_suppress 64
62#endif
63
64
65/* OOC header, please DO NOT modify */
66#ifdef __ARM_2D_HELPER_IMPLEMENT__
67# define __ARM_2D_IMPL__
68#elif defined(__ARM_2D_HELPER_INHERIT__)
69# undef __ARM_2D_HELPER_INHERIT__
70# define __ARM_2D_INHERIT__
71#endif
72#include "arm_2d_utils.h"
73
74/*!
75 * \addtogroup Deprecated
76 * @{
77 */
78#define arm_2d_draw_box arm_2d_helper_draw_box
79/*! @} */
80
81/*!
82 * \addtogroup gHelper 8 Helper Services
83 * @{
84 */
85/*============================ MACROS ========================================*/
86/*============================ MACROFIED FUNCTIONS ===========================*/
87
88/*!
89 * \brief set an alarm with given period and check the status
90 *
91 * \param[in] __ms a time period in millisecond
92 * \param[in] ... an optional timestamp holder
93 *
94 * \return bool whether it is timeout
95 */
96#define arm_2d_helper_is_time_out(__ms, ...) \
97 ({ static int64_t arm_2d_safe_name(s_lTimestamp); \
98 __arm_2d_helper_is_time_out(arm_2d_helper_convert_ms_to_ticks(__ms), \
99 (&arm_2d_safe_name(s_lTimestamp),##__VA_ARGS__));})
100
101
102#define arm_2d_helper_time_elapsed(__timestamp_ptr) \
103 arm_2d_helper_convert_ticks_to_ms( \
104 __arm_2d_helper_time_elapsed(__timestamp_ptr))
105
106/*!
107 * \brief calculate the stroke of a liner slider based on time
108 *
109 * \param[in] __from the start of the slider
110 * \param[in] __to the end of the slider
111 * \param[in] __ms a given period (ms) in which the slider should finish the
112 * whole stroke
113 * \param[out] __stroke_ptr the address of an int32_t stroke variable
114 * \param[in] ... an optional address of a timestamp variable, if you omit it,
115 * NULL will be passed, and the code that call this funtion will not
116 * be reentrant.
117 * \retval true the slider has finished the whole stroke
118 * \retval false the slider hasn't reach the target end
119 */
120#define arm_2d_helper_time_liner_slider( __from, \
121 __to, \
122 __ms, \
123 __stroke_ptr, \
124 ...) \
125 ({static int64_t arm_2d_safe_name(s_lTimestamp); \
126 __arm_2d_helper_time_liner_slider((__from), \
127 (__to), \
128 arm_2d_helper_convert_ms_to_ticks(__ms), \
129 (__stroke_ptr), \
130 (&arm_2d_safe_name(s_lTimestamp),##__VA_ARGS__));})
131
132/*!
133 * \brief calculate the stroke of a cosine slider based on time
134 *
135 * \param[in] __from the start of the slider
136 * \param[in] __to the end of the slider
137 * \param[in] __ms a given period (ms) in which the slider should finish the
138 * whole stroke
139 * \param[in] __phase the phase offset
140 * \param[out] __stroke_ptr the address of an int32_t stroke variable
141 * \param[in] ... an optional address of a timestamp variable, if you omit it,
142 * NULL will be passed, and the code that call this funtion will not
143 * be reentrant.
144 * \retval true the slider has finished the whole stroke
145 * \retval false the slider hasn't reach the target end
146 */
147#define arm_2d_helper_time_cos_slider( __from, \
148 __to, \
149 __ms, \
150 __phase, \
151 __stroke_ptr, \
152 ...) \
153 ({static int64_t arm_2d_safe_name(s_lTimestamp); \
154 __arm_2d_helper_time_cos_slider((__from), \
155 (__to), \
156 arm_2d_helper_convert_ms_to_ticks(__ms), \
157 (__phase), \
158 (__stroke_ptr), \
159 (&arm_2d_safe_name(s_lTimestamp),##__VA_ARGS__));})
160
161/*!
162 * \brief calculate the stroke of a cosine slider(0~pi) based on time
163 *
164 * \param[in] __from the start of the slider
165 * \param[in] __to the end of the slider
166 * \param[in] __ms a given period (ms) in which the slider should finish the
167 * whole stroke
168 * \param[out] __stroke_ptr the address of an int32_t stroke variable
169 * \param[in] ... an optional address of a timestamp variable, if you omit it,
170 * NULL will be passed, and the code that call this funtion will not
171 * be reentrant.
172 * \retval true the slider has finished the whole stroke
173 * \retval false the slider hasn't reach the target end
174 */
175#define arm_2d_helper_time_half_cos_slider( __from, \
176 __to, \
177 __ms, \
178 __stroke_ptr, \
179 ...) \
180 ({static int64_t arm_2d_safe_name(s_lTimestamp); \
181 __arm_2d_helper_time_half_cos_slider((__from), \
182 (__to), \
183 arm_2d_helper_convert_ms_to_ticks(__ms), \
184 (__stroke_ptr), \
185 (&arm_2d_safe_name(s_lTimestamp),##__VA_ARGS__));})
186
187
188/*!
189 * \brief initialize/implement a given film (arm_2d_helper_file_t) object
190 * at compile-time.
191 * \param[in] __sprites_tile the sprites tile
192 * \param[in] __width the width of each frame
193 * \param[in] __height the height of each frame
194 * \param[in] __column the number of frames per row in the sprite tile
195 * \param[in] __frame_count the total number of frames in the sprite tile
196 * \param[in] __period the period per-frame
197 * \note __period is used as a reference for applications. The helper service
198 * doesn't use it at all.
199 */
200#define impl_film( __sprites_tile, \
201 __width, \
202 __height, \
203 __column, \
204 __frame_count, \
205 __period) \
206 { \
207 .use_as__arm_2d_tile_t = \
208 impl_child_tile((__sprites_tile), 0, 0, (__width), (__height)), \
209 .hwColumn = (__column), \
210 .hwFrameNum = (__frame_count), \
211 .hwPeriodPerFrame = (__period), \
212 }
213
214/*============================ TYPES =========================================*/
215
216/*!
217 * \brief a helper class to represent a GIF-like resource
218 */
219typedef struct arm_2d_helper_film_t {
220 implement(arm_2d_tile_t); /*!< derived from arm_2d_tile_t */
221 uint16_t hwColumn; /*!< number of frames per row in a sprite tile */
222 uint16_t hwFrameNum; /*!< the total number of frames */
223 uint16_t hwPeriodPerFrame; /*!< the period per frame (optional, used as a reference) */
224 uint16_t hwFrameIndex; /*!< the frame index used at runtime */
226
227/*!
228 * \brief the configuration structure for the Proportional-Integral Control
229 *
230 */
232 int32_t nInterval;
233 float fProportion;
234 float fIntegration;
236
237/*!
238 * \brief a helper class for Proportional-Integral Control
239 */
241
242ARM_PRIVATE (
244 int64_t lTimestamp;
245 int32_t nTimeResidual;
246 float fCurrent;
247 float fOP;
250
252 uint16_t hwPointer;
253 uint16_t hwDataAvailable;
254};
255
256typedef struct arm_2d_byte_fifo_t {
257ARM_PROTECTED (
258 uint8_t *pchBuffer;
259 uint16_t hwSize;
260 uint16_t hwTail;
261
262 struct __arm_2d_fifo_reader_pointer tHead;
263 struct __arm_2d_fifo_reader_pointer tPeek;
264)
266
267/*============================ GLOBAL VARIABLES ==============================*/
268/*============================ LOCAL VARIABLES ===============================*/
269/*============================ PROTOTYPES ====================================*/
270
271/*!
272 * \brief initialize helper services
273 */
274extern
276
277/*!
278 * \brief backend task for asynchronose mode
279 */
280extern
282
283/*!
284 * \brief convert ticks of a reference timer to millisecond
285 *
286 * \param[in] lTick the tick count
287 * \return int64_t the millisecond
288 */
289extern
291
292/*!
293 * \brief convert millisecond into ticks of the reference timer
294 *
295 * \param[in] wMS the target time in millisecond
296 * \return int64_t the ticks
297 */
298extern
300
301/*!
302 * \brief get the reference clock frequency
303 * \return uint32_t the frequency
304 */
305extern
307
308/*!
309 * \brief get the current system stamp from the reference clock
310 *
311 * \return int64_t the timestamp in ticks
312 * \note you have to call arm_2d_helper_convert_ticks_to_ms() to convert the
313 * the timestamp into milliseconds when required.
314 */
315extern
317
318/*!
319 * \brief get the elapsed time since a reference timestamp
320 * \param[in] plTimestamp the reference timestamp
321 * \return int64_t the timestamp in ticks
322 */
323extern
324ARM_NONNULL(1)
325int64_t __arm_2d_helper_time_elapsed(int64_t *plTimestamp);
326
327/*!
328 * \brief set an alarm with given period and check the status
329 *
330 * \param[in] lPeriod a time period in ticks
331 * \param[in] plTimestamp a pointer points to an int64_t integer, if NULL is
332 * passed, an static local variable inside the function will be used
333 * \return bool whether it is timeout or not
334 */
335ARM_NONNULL(2)
336extern
337bool __arm_2d_helper_is_time_out(int64_t lPeriod, int64_t *plTimestamp);
338
339/*!
340 * \brief get a new semaphore from host RTOS
341 * \return uintptr_t a handler for the semaphore
342 */
343extern
345
346/*!
347 * \brief free a semaphore
348 * \param[in] pSemaphore the target semaphore
349 */
350extern
351void arm_2d_port_free_semaphore(uintptr_t pSemaphore);
352
353/*!
354 * \brief wait for a semaphore
355 * \param[in] pSemaphore the target semaphore
356 * \retval true we get the semaphore
357 * \retval false we haven't get the sempahore
358 */
359extern
360bool arm_2d_port_wait_for_semaphore(uintptr_t pSemaphore);
361
362/*!
363 * \brief set a semaphore
364 * \param[in] pSemaphore the target semaphore
365 */
366extern
367void arm_2d_port_set_semaphore(uintptr_t pSemaphore);
368
369/*!
370 * \brief calculate the stroke of a liner slider based on time
371 *
372 * \param[in] nFrom the start of the slider
373 * \param[in] nTo the end of the slider
374 * \param[in] lPeriod a given period in which the slider should finish the whole
375 * stroke
376 * \param[out] pnStroke the address of an int32_t stroke variable
377 * \param[in] plTimestamp the address of a timestamp variable, if you pass NULL
378 * the code that call this funtion will not be reentrant.
379 * \retval true the slider has finished the whole stroke
380 * \retval false the slider hasn't reach the target end
381 */
382ARM_NONNULL(4,5)
383extern
385 int32_t nTo,
386 int64_t lPeriod,
387 int32_t *pnStroke,
388 int64_t *plTimestamp);
389
390/*!
391 * \brief calculate the stroke of a cosine slider (0~pi) based on time
392 *
393 * \param[in] nFrom the start of the slider
394 * \param[in] nTo the end of the slider
395 * \param[in] lPeriod a given period in which the slider should finish the whole
396 * stroke
397 * \param[out] pnStroke the address of an int32_t stroke variable
398 * \param[in] plTimestamp the address of a timestamp variable, if you pass NULL
399 * the code that call this funtion will not be reentrant.
400 * \retval true the slider has finished the whole stroke
401 * \retval false the slider hasn't reach the target end
402 */
403ARM_NONNULL(4,5)
404extern
406 int32_t nTo,
407 int64_t lPeriod,
408 int32_t *pnStroke,
409 int64_t *plTimestamp);
410
411/*!
412 * \brief calculate the stroke of a consine slider (0~2pi) based on time
413 *
414 * \param[in] nFrom the start of the slider
415 * \param[in] nTo the end of the slider
416 * \param[in] lPeriod a given period in which the slider should finish the whole
417 * stroke
418 * \param[in] lPhase the phase offset
419 * \param[out] pnStroke the address of an int32_t stroke variable
420 * \param[in] plTimestamp the address of a timestamp variable, if you pass NULL
421 * the code that call this funtion will not be reentrant.
422 * \retval true the slider has finished the whole stroke
423 * \retval false the slider hasn't reach the target end
424 */
425ARM_NONNULL(5,6)
426extern
428 int32_t nTo,
429 int64_t lPeriod,
430 float fPhase,
431 int32_t *pnStroke,
432 int64_t *plTimestamp);
433
434/*!
435 * \brier colour intrapolation
436 * \param[in] wFrom a 32bit colour (4 8bit colour channels) on the start
437 * \param[in] wTo a 32bit colour (4 8bit colour channels) on the end
438 * \param[in] nDistance the reference full distance between two end points
439 * \param[in] nOffset the offset from the start
440 * \return uint32_t 32bit colour
441 */
442extern
443uint32_t __arm_2d_helper_colour_slider( uint32_t wFrom,
444 uint32_t wTo,
445 int32_t nDistance,
446 int32_t nOffset);
447
448/*!
449 * \brief initialize the Proportional-Integral Control helper
450 * \param[in] the target helper control block
451 * \param[in] the configuration structure, NULL means using the default
452 * parameters, i.e P = 5.0f, I = 3.0f and Interval = 20ms
453 * \param[in] nStartPosition the start postion
454 * \return arm_2d_helper_pi_slider_t* the control block
455 */
456extern
457ARM_NONNULL(1)
461 int32_t nStartPosition);
462
463/*!
464 * \brief A helper function for Proportional-Integral Control
465 * \param[in] ptThis the control block (arm_2d_helper_pi_slider_t)
466 * \param[in] nTargetPosition the new target position
467 * \param[in] pnResult a int32_t buffer for reading the current postion
468 * \retval true the slider has reached the target postion
469 * \retval false the slider is still moving
470 */
471extern
472ARM_NONNULL( 1, 3 )
474 int32_t nTargetPosition,
475 int32_t *pnResult);
476
477/*!
478 * \brief reset the PI slider and set the current value
479 * \param[in] ptThis the control block (arm_2d_helper_pi_slider_t)
480 * \param[in] nCurrent the new current value
481 */
482extern
483ARM_NONNULL(1)
485 int32_t nCurrent);
486
487/*!
488 * \brief A helper function for Proportional-Integral Control
489 * \param[in] ptThis the control block (arm_2d_helper_pi_slider_t)
490 * \param[in] fTargetPosition the new target position
491 * \param[in] pfResult a int32_t buffer for reading the current postion
492 * \retval true the slider has reached the target postion
493 * \retval false the slider is still moving
494 */
495extern
496ARM_NONNULL( 1, 3 )
498 float fTargetPosition,
499 float *pfResult);
500
501/*!
502 * \brief reset the PI slider and set the current value
503 * \param[in] ptThis the control block (arm_2d_helper_pi_slider_t)
504 * \param[in] fCurrent the new current value
505 */
506extern
507ARM_NONNULL(1)
510 float fCurrent);
511
512/*!
513 * \brier draw a box with specified colour, border width and opacity
514 * \param[in] ptTarget the target tile
515 * \param[in] ptRegion the target region
516 * \param[in] iBorderWidth the border width
517 * \param[in] tColour the target colour
518 * \param[in] chOpacity the opacity
519 */
520extern
522 const arm_2d_region_t *ptRegion,
523 int16_t iBorderWidth,
524 COLOUR_INT tColour,
525 uint8_t chOpacity);
526
527/*!
528 * \brier move to the next frame of a given film
529 * \param[in] ptThis the target film
530 */
531extern
532ARM_NONNULL(1)
534
535/*!
536 * \brier reset the frame index to zero
537 * \param[in] ptThis the target film
538 */
539extern
540ARM_NONNULL(1)
542
543/*!
544 * \brier reset the frame index to a specified value and wrap around if the
545 * index number is out of range.
546 * \param[in] ptThis the target film
547 * \param[in] nIndex the given index
548 */
549extern
550ARM_NONNULL(1)
552
553/*----------------------------------------------------------------------------*
554 * FIFO Helper Service *
555 *----------------------------------------------------------------------------*/
556
557/*!
558 * \brief initialize a given byte fifo
559 * \param[in] ptThis the target FIFO control block
560 * \param[in] pBuffer a buffer for storing the data
561 * \param[in] hwSize the buffer size
562 * \retval false Illegal parameters
563 * \retval true the target FIFO is initialized
564 */
565extern
566ARM_NONNULL(1,2)
568 void *pBuffer,
569 uint16_t hwSize);
570
571/*!
572 * \brief Empty a given byte fifo
573 * \param[in] ptThis the target byte fifo
574 */
575extern
576ARM_NONNULL(1)
578
579/*!
580 * \brief write a byte to a given fifo
581 * \param[in] ptThis the target FIFO control block
582 * \param[in] chChar the target byte
583 * \retval false the FIFO is FULL
584 * \retval true operation is successful
585 */
586extern
587ARM_NONNULL(1)
588bool arm_2d_byte_fifo_enqueue(arm_2d_byte_fifo_t *ptThis, uint8_t chChar);
589
590/*!
591 * \brief read a byte from a given fifo
592 * \param[in] ptThis the target FIFO control block
593 * \param[in] pchChar a buffer to store the byte, NULL means drop a byte
594 * \retval false the FIFO is EMPTY
595 * \retval true operation is successful
596 */
597extern
598ARM_NONNULL(1)
599bool arm_2d_byte_fifo_dequeue(arm_2d_byte_fifo_t *ptThis, uint8_t *pchChar);
600
601/*!
602 * \brief peek a byte continuously from a given fifo
603 * \param[in] ptThis the target FIFO control block
604 * \param[in] pchChar a buffer to store the byte, NULL means drop a byte
605 * \retval false the FIFO is EMPTY
606 * \retval true operation is successful
607 */
608extern
609ARM_NONNULL(1)
611 uint8_t *pchChar,
612 bool bMovePointer);
613
614/*!
615 * \brief drop all peeked byte from a given fifo
616 * \param[in] ptThis the target FIFO control block
617 * \return none
618 */
619extern
620ARM_NONNULL(1)
622
623/*!
624 * \brief reset the peek pointer, so you can restart from the beginning to peek.
625 * \param[in] ptThis the target FIFO control block
626 * \return none
627 */
628ARM_NONNULL(1)
630
631/*----------------------------------------------------------------------------*
632 * Misc *
633 *----------------------------------------------------------------------------*/
634
635/*!
636 * \brief swap the high and low bytes for each rgb16 pixel
637 *
638 * \param[in] phwBuffer the pixel buffer
639 * \note the phwBuffer MUST aligned to half-word addresses
640 *
641 * \param[in] wSize the number of pixels
642 */
643extern
644void arm_2d_helper_swap_rgb16(uint16_t *phwBuffer, uint32_t wCount);
645
646extern
647ARM_NONNULL(1)
648/*!
649 * \brief fill the target tile with a specified colour
650 *
651 * \param[in] ptTile the target tile
652 * \param[in] tColourFormat the colour format of the target tile
653 * \param[in] tColour the target colour
654 */
656 arm_2d_color_info_t tColourFormat,
657 arm_2d_colour_t tColour);
658
659#if __ARM_2D_HELPER_CFG_LAYOUT_DEBUG_MODE__
660extern
661ARM_NONNULL(1)
662void __arm_2d_helper_layout_debug_print_label(const arm_2d_tile_t *ptTile,
663 arm_2d_region_t *ptRegion,
664 const char *pchString);
665#endif
666
667/*! @} */
668
669/*============================ INCLUDES ======================================*/
670#include "arm_2d_helper_built_in.h"
671
672#if defined(__clang__)
673# pragma clang diagnostic pop
674#elif __IS_COMPILER_ARM_COMPILER_5__
675#pragma diag_warning 64
676#endif
677
678#undef __ARM_2D_HELPER_IMPLEMENT__
679#undef __ARM_2D_HELPER_INHERIT__
680
681
682#ifdef __cplusplus
683}
684#endif
685
686#endif