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: 06. Nov 2024
25 * $Revision: V.2.1.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 (
243 q16_t q16Proportion;
244 q16_t q16Integration;
245 q16_t q16Current;
246 q16_t q16OP;
247 int32_t nInterval;
248
249 int64_t lTimestamp;
250 int32_t nTimeResidual;
252
254
256 uint16_t hwPointer;
257 uint16_t hwDataAvailable;
258};
259
260typedef struct arm_2d_byte_fifo_t {
261ARM_PROTECTED (
262 uint8_t *pchBuffer;
263 uint16_t hwSize;
264 uint16_t hwTail;
265
266 struct __arm_2d_fifo_reader_pointer tHead;
267 struct __arm_2d_fifo_reader_pointer tPeek;
268)
270
271/*============================ GLOBAL VARIABLES ==============================*/
272/*============================ LOCAL VARIABLES ===============================*/
273/*============================ PROTOTYPES ====================================*/
274
275/*!
276 * \brief initialize helper services
277 */
278extern
280
281/*!
282 * \brief backend task for asynchronose mode
283 */
284extern
286
287/*!
288 * \brief convert ticks of a reference timer to millisecond
289 *
290 * \param[in] lTick the tick count
291 * \return int64_t the millisecond
292 */
293extern
295
296/*!
297 * \brief convert millisecond into ticks of the reference timer
298 *
299 * \param[in] wMS the target time in millisecond
300 * \return int64_t the ticks
301 */
302extern
304
305/*!
306 * \brief get the reference clock frequency
307 * \return uint32_t the frequency
308 */
309extern
311
312/*!
313 * \brief get the current system stamp from the reference clock
314 *
315 * \return int64_t the timestamp in ticks
316 * \note you have to call arm_2d_helper_convert_ticks_to_ms() to convert the
317 * the timestamp into milliseconds when required.
318 */
319extern
321
322/*!
323 * \brief get the elapsed time since a reference timestamp
324 * \param[in] plTimestamp the reference timestamp
325 * \return int64_t the timestamp in ticks
326 */
327extern
328ARM_NONNULL(1)
329int64_t __arm_2d_helper_time_elapsed(int64_t *plTimestamp);
330
331/*!
332 * \brief set an alarm with given period and check the status
333 *
334 * \param[in] lPeriod a time period in ticks
335 * \param[in] plTimestamp a pointer points to an int64_t integer, if NULL is
336 * passed, an static local variable inside the function will be used
337 * \return bool whether it is timeout or not
338 */
339ARM_NONNULL(2)
340extern
341bool __arm_2d_helper_is_time_out(int64_t lPeriod, int64_t *plTimestamp);
342
343/*!
344 * \brief get a new semaphore from host RTOS
345 * \return uintptr_t a handler for the semaphore
346 */
347extern
349
350/*!
351 * \brief free a semaphore
352 * \param[in] pSemaphore the target semaphore
353 */
354extern
355void arm_2d_port_free_semaphore(uintptr_t pSemaphore);
356
357/*!
358 * \brief wait for a semaphore
359 * \param[in] pSemaphore the target semaphore
360 * \retval true we get the semaphore
361 * \retval false we haven't get the sempahore
362 */
363extern
364bool arm_2d_port_wait_for_semaphore(uintptr_t pSemaphore);
365
366/*!
367 * \brief set a semaphore
368 * \param[in] pSemaphore the target semaphore
369 */
370extern
371void arm_2d_port_set_semaphore(uintptr_t pSemaphore);
372
373/*!
374 * \brief calculate the stroke of a liner slider based on time
375 *
376 * \param[in] nFrom the start of the slider
377 * \param[in] nTo the end of the slider
378 * \param[in] lPeriod a given period in which the slider should finish the whole
379 * stroke
380 * \param[out] pnStroke the address of an int32_t stroke variable
381 * \param[in] plTimestamp the address of a timestamp variable, if you pass NULL
382 * the code that call this funtion will not be reentrant.
383 * \retval true the slider has finished the whole stroke
384 * \retval false the slider hasn't reach the target end
385 */
386ARM_NONNULL(4,5)
387extern
389 int32_t nTo,
390 int64_t lPeriod,
391 int32_t *pnStroke,
392 int64_t *plTimestamp);
393
394/*!
395 * \brief calculate the stroke of a cosine slider (0~pi) based on time
396 *
397 * \param[in] nFrom the start of the slider
398 * \param[in] nTo the end of the slider
399 * \param[in] lPeriod a given period in which the slider should finish the whole
400 * stroke
401 * \param[out] pnStroke the address of an int32_t stroke variable
402 * \param[in] plTimestamp the address of a timestamp variable, if you pass NULL
403 * the code that call this funtion will not be reentrant.
404 * \retval true the slider has finished the whole stroke
405 * \retval false the slider hasn't reach the target end
406 */
407ARM_NONNULL(4,5)
408extern
410 int32_t nTo,
411 int64_t lPeriod,
412 int32_t *pnStroke,
413 int64_t *plTimestamp);
414
415/*!
416 * \brief calculate the stroke of a consine slider (0~2pi) based on time
417 *
418 * \param[in] nFrom the start of the slider
419 * \param[in] nTo the end of the slider
420 * \param[in] lPeriod a given period in which the slider should finish the whole
421 * stroke
422 * \param[in] lPhase the phase offset
423 * \param[out] pnStroke the address of an int32_t stroke variable
424 * \param[in] plTimestamp the address of a timestamp variable, if you pass NULL
425 * the code that call this funtion will not be reentrant.
426 * \retval true the slider has finished the whole stroke
427 * \retval false the slider hasn't reach the target end
428 */
429ARM_NONNULL(5,6)
430extern
432 int32_t nTo,
433 int64_t lPeriod,
434 float fPhase,
435 int32_t *pnStroke,
436 int64_t *plTimestamp);
437
438/*!
439 * \brier colour intrapolation
440 * \param[in] wFrom a 32bit colour (4 8bit colour channels) on the start
441 * \param[in] wTo a 32bit colour (4 8bit colour channels) on the end
442 * \param[in] nDistance the reference full distance between two end points
443 * \param[in] nOffset the offset from the start
444 * \return uint32_t 32bit colour
445 */
446extern
447uint32_t __arm_2d_helper_colour_slider( uint32_t wFrom,
448 uint32_t wTo,
449 int32_t nDistance,
450 int32_t nOffset);
451
452/*!
453 * \brief initialize the Proportional-Integral Control helper
454 * \param[in] the target helper control block
455 * \param[in] the configuration structure, NULL means using the default
456 * parameters, i.e P = 5.0f, I = 3.0f and Interval = 20ms
457 * \param[in] iStartPosition the start postion
458 * \return arm_2d_helper_pi_slider_t* the control block
459 */
460extern
461ARM_NONNULL(1)
465 int16_t iStartPosition);
466
467/*!
468 * \brief A helper function for Proportional-Integral Control
469 * \param[in] ptThis the control block (arm_2d_helper_pi_slider_t)
470 * \param[in] iTargetPosition the new target position
471 * \param[in] piResult a int32_t buffer for reading the current postion
472 * \retval true the slider has reached the target postion
473 * \retval false the slider is still moving
474 */
475extern
476ARM_NONNULL( 1, 3 )
478 int16_t iTargetPosition,
479 int16_t *piResult);
480
481/*!
482 * \brief reset the PI slider and set the current value
483 * \param[in] ptThis the control block (arm_2d_helper_pi_slider_t)
484 * \param[in] iCurrent the new current value
485 */
486extern
487ARM_NONNULL(1)
489 int16_t iCurrent);
490
491/*!
492 * \brief A helper function for Proportional-Integral Control
493 * \param[in] ptThis the control block (arm_2d_helper_pi_slider_t)
494 * \param[in] fTargetPosition the new target position
495 * \param[in] pfResult a int32_t buffer for reading the current postion
496 * \retval true the slider has reached the target postion
497 * \retval false the slider is still moving
498 */
499extern
500ARM_NONNULL( 1, 3 )
502 float fTargetPosition,
503 float *pfResult);
504
505/*!
506 * \brief reset the PI slider and set the current value
507 * \param[in] ptThis the control block (arm_2d_helper_pi_slider_t)
508 * \param[in] fCurrent the new current value
509 */
510extern
511ARM_NONNULL(1)
514 float fCurrent);
515
516/*!
517 * \brier draw a box with specified colour, border width and opacity
518 * \param[in] ptTarget the target tile
519 * \param[in] ptRegion the target region
520 * \param[in] iBorderWidth the border width
521 * \param[in] tColour the target colour
522 * \param[in] chOpacity the opacity
523 */
524extern
526 const arm_2d_region_t *ptRegion,
527 int16_t iBorderWidth,
528 COLOUR_INT tColour,
529 uint8_t chOpacity);
530
531/*!
532 * \brier move to the next frame of a given film
533 * \param[in] ptThis the target film
534 */
535extern
536ARM_NONNULL(1)
538
539/*!
540 * \brier reset the frame index to zero
541 * \param[in] ptThis the target film
542 */
543extern
544ARM_NONNULL(1)
546
547/*!
548 * \brier reset the frame index to a specified value and wrap around if the
549 * index number is out of range.
550 * \param[in] ptThis the target film
551 * \param[in] nIndex the given index
552 */
553extern
554ARM_NONNULL(1)
556
557/*----------------------------------------------------------------------------*
558 * FIFO Helper Service *
559 *----------------------------------------------------------------------------*/
560
561/*!
562 * \brief initialize a given byte fifo
563 * \param[in] ptThis the target FIFO control block
564 * \param[in] pBuffer a buffer for storing the data
565 * \param[in] hwSize the buffer size
566 * \retval false Illegal parameters
567 * \retval true the target FIFO is initialized
568 */
569extern
570ARM_NONNULL(1,2)
572 void *pBuffer,
573 uint16_t hwSize);
574
575/*!
576 * \brief Empty a given byte fifo
577 * \param[in] ptThis the target byte fifo
578 */
579extern
580ARM_NONNULL(1)
582
583/*!
584 * \brief write a byte to a given fifo
585 * \param[in] ptThis the target FIFO control block
586 * \param[in] chChar the target byte
587 * \retval false the FIFO is FULL
588 * \retval true operation is successful
589 */
590extern
591ARM_NONNULL(1)
592bool arm_2d_byte_fifo_enqueue(arm_2d_byte_fifo_t *ptThis, uint8_t chChar);
593
594/*!
595 * \brief read a byte from a given fifo
596 * \param[in] ptThis the target FIFO control block
597 * \param[in] pchChar a buffer to store the byte, NULL means drop a byte
598 * \retval false the FIFO is EMPTY
599 * \retval true operation is successful
600 */
601extern
602ARM_NONNULL(1)
603bool arm_2d_byte_fifo_dequeue(arm_2d_byte_fifo_t *ptThis, uint8_t *pchChar);
604
605/*!
606 * \brief peek a byte continuously from a given fifo
607 * \param[in] ptThis the target FIFO control block
608 * \param[in] pchChar a buffer to store the byte, NULL means drop a byte
609 * \retval false the FIFO is EMPTY
610 * \retval true operation is successful
611 */
612extern
613ARM_NONNULL(1)
615 uint8_t *pchChar,
616 bool bMovePointer);
617
618/*!
619 * \brief drop all peeked byte from a given fifo
620 * \param[in] ptThis the target FIFO control block
621 * \return none
622 */
623extern
624ARM_NONNULL(1)
626
627/*!
628 * \brief reset the peek pointer, so you can restart from the beginning to peek.
629 * \param[in] ptThis the target FIFO control block
630 * \return none
631 */
632ARM_NONNULL(1)
634
635/*----------------------------------------------------------------------------*
636 * Misc *
637 *----------------------------------------------------------------------------*/
638
639/*!
640 * \brief swap the high and low bytes for each rgb16 pixel
641 *
642 * \param[in] phwBuffer the pixel buffer
643 * \note the phwBuffer MUST aligned to half-word addresses
644 *
645 * \param[in] wSize the number of pixels
646 */
647extern
648void arm_2d_helper_swap_rgb16(uint16_t *phwBuffer, uint32_t wCount);
649
650extern
651ARM_NONNULL(1)
652/*!
653 * \brief fill the target tile with a specified colour
654 *
655 * \param[in] ptTile the target tile
656 * \param[in] tColourFormat the colour format of the target tile
657 * \param[in] tColour the target colour
658 */
660 arm_2d_color_info_t tColourFormat,
661 arm_2d_colour_t tColour);
662
663#if __ARM_2D_HELPER_CFG_LAYOUT_DEBUG_MODE__
664extern
665ARM_NONNULL(1)
666void __arm_2d_helper_layout_debug_print_label(const arm_2d_tile_t *ptTile,
667 arm_2d_region_t *ptRegion,
668 const char *pchString);
669#endif
670
671/*! @} */
672
673/*============================ INCLUDES ======================================*/
674#include "arm_2d_helper_built_in.h"
675
676#if defined(__clang__)
677# pragma clang diagnostic pop
678#elif __IS_COMPILER_ARM_COMPILER_5__
679#pragma diag_warning 64
680#endif
681
682#undef __ARM_2D_HELPER_IMPLEMENT__
683#undef __ARM_2D_HELPER_INHERIT__
684
685
686#ifdef __cplusplus
687}
688#endif
689
690#endif