├── README.md ├── comm ├── gsmmng.c ├── gsmmng.h ├── wifimng.c └── wifimng.h ├── fs ├── fat32 │ ├── fat32.c │ ├── fat32.h │ ├── fat32_readme.txt │ ├── ff.c │ ├── ff.h │ ├── ffconf.h │ ├── integer.h │ └── option │ │ ├── ccsbcs.c │ │ └── syscall.c ├── fsint.c ├── fsint.h ├── linuxfs │ ├── linuxfs.c │ └── linuxfs.h └── ufs │ ├── ufs.c │ └── ufs.h ├── gfx ├── anim.c ├── anim.h ├── area.c ├── area.h ├── circ.c ├── circ.h ├── color.h ├── font.c ├── font.h ├── fonts │ ├── dejavu_10.c │ ├── dejavu_10.h │ ├── dejavu_120.c │ ├── dejavu_120.h │ ├── dejavu_14.c │ ├── dejavu_14.h │ ├── dejavu_20.c │ ├── dejavu_20.h │ ├── dejavu_30.c │ ├── dejavu_30.h │ ├── dejavu_40.c │ ├── dejavu_40.h │ ├── dejavu_60.c │ ├── dejavu_60.h │ ├── dejavu_8.c │ ├── dejavu_8.h │ ├── dejavu_80.c │ ├── dejavu_80.h │ ├── symbol_30.c │ ├── symbol_30.h │ ├── symbol_60.c │ ├── symbol_60.h │ └── symbol_def.h ├── text.c └── text.h ├── licence.txt ├── math ├── math_base.h ├── trigo.c └── trigo.h ├── mem ├── dyn_mem.c ├── dyn_mem.h ├── dyn_mem_defr.c ├── dyn_mem_defr.h ├── fifo.c ├── fifo.h ├── linked_list.c └── linked_list.h ├── misc.c ├── misc.h ├── misc_conf_templ.h ├── os ├── idle.c ├── idle.h ├── ptask.c └── ptask.h ├── others ├── fsm.c ├── fsm.h ├── slip.c ├── slip.h ├── strcmd.c └── strcmd.h └── templ ├── templ.c └── templ.h /README.md: -------------------------------------------------------------------------------- 1 | # Miscellaneous Library 2 | 3 | Some of the most important components: 4 | * Dynamic memory manager with defrag. and memory monitoring 5 | * Simple task scheduler with priority and idle measurement 6 | * File system interface to access different mediums easily 7 | * RAM FS 8 | * FIFO 9 | * Linked list 10 | * Fonts 11 | * etc 12 | 13 | ## Usage 14 | 1. Clone the repository into the root folder of your project: `git clone https://github.com/littlevgl/misc.git` 15 | 2. In your IDE add the project **root folder as include path** 16 | 3. Copy *misc/misc_conf_templ.h* as **misc_conf.h** to the project root folder 17 | 4. Delete the first `#if 0` and the last `#endif` to enable the file 18 | 5. Enable/disable or configure the components 19 | 6. To initialize the library `#include misc/misc.h` and call `misc_init()` 20 | -------------------------------------------------------------------------------- /comm/gsmmng.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file gsmmng.c 3 | * 4 | */ 5 | 6 | /********************* 7 | * INCLUDES 8 | *********************/ 9 | #include "gsmmng.h" 10 | #if USE_GSMMNG != 0 11 | 12 | #include 13 | #include "hal/gsm/gsm.h" 14 | #include "hal/systick/systick.h" 15 | #include "../os/ptask.h" 16 | #include "hw/dev/ui/log.h" 17 | 18 | 19 | 20 | /********************* 21 | * DEFINES 22 | *********************/ 23 | 24 | /********************** 25 | * TYPEDEFS 26 | **********************/ 27 | 28 | /********************** 29 | * STATIC PROTOTYPES 30 | **********************/ 31 | static gsmmng_state_t gsmmng_state; 32 | static uint32_t gsmmng_timestamp = 0; 33 | static char last_apn[128]; 34 | static char last_ip[32]; 35 | static char last_port[16]; 36 | 37 | static void gsmmng_task(void * param); 38 | static void gsmmng_netw_leave(gsm_state_t state, const char * txt); 39 | static void gsmmng_netw_con_cb(gsm_state_t state, const char * txt); 40 | static void gsmmng_tcp_leave_cb(gsm_state_t state, const char * txt); 41 | static void gsmmng_tcp_con_cb(gsm_state_t state, const char * txt); 42 | 43 | /********************** 44 | * STATIC VARIABLES 45 | **********************/ 46 | LOG_FN("gsmmng"); 47 | 48 | /********************** 49 | * MACROS 50 | **********************/ 51 | 52 | /********************** 53 | * GLOBAL FUNCTIONS 54 | **********************/ 55 | void gsmmng_init(void) 56 | { 57 | gsmmng_state = GSMMNG_STATE_IDLE; 58 | ptask_create(gsmmng_task, 1000, PTASK_PRIO_LOW, NULL); 59 | } 60 | 61 | 62 | void gsmmng_set_last_apn(const char * apn) 63 | { 64 | strcpy(last_apn, apn); 65 | gsmmng_state = GSMMNG_STATE_NETW_CON; 66 | } 67 | 68 | void gsmmng_set_last_tcp(const char * ip, const char * port) 69 | { 70 | strcpy(last_ip, ip); 71 | strcpy(last_port, port); 72 | gsmmng_state = GSMMNG_STATE_NETW_CON; 73 | } 74 | 75 | gsmmng_state_t gsmmng_get_state(void) 76 | { 77 | return gsmmng_state; 78 | } 79 | 80 | void gsmmng_reconnect(void) 81 | { 82 | gsmmng_state = GSMMNG_STATE_NETW_LEAVE; 83 | } 84 | 85 | const char * gsmmng_get_last_apn(void) 86 | { 87 | return last_apn; 88 | } 89 | 90 | const char * gsmmng_get_last_ip(void) 91 | { 92 | return last_ip; 93 | } 94 | 95 | const char * gsmmng_get_last_port(void) 96 | { 97 | return last_port; 98 | } 99 | 100 | /********************** 101 | * STATIC FUNCTIONS 102 | **********************/ 103 | 104 | static void gsmmng_task(void * param) 105 | { 106 | 107 | if(last_apn[0] == '\0' || last_ip[0] == '\0' || last_port[0] == '\0') { 108 | return; 109 | } 110 | 111 | switch(gsmmng_state) { 112 | 113 | case GSMMNG_STATE_NETW_LEAVE: 114 | SMSG("netw_leave"); 115 | if(gsm_busy() != false) break; 116 | 117 | gsm_netw_leave(gsmmng_netw_leave); 118 | gsmmng_state = GSMMNG_STATE_WAIT; 119 | break; 120 | 121 | case GSMMNG_STATE_NETW_CON: 122 | SMSG("netw con"); 123 | gsm_netw_con(last_apn, gsmmng_netw_con_cb); 124 | gsmmng_state = GSMMNG_STATE_WAIT; 125 | break; 126 | 127 | 128 | case GSMMNG_STATE_TCP_LEAVE: 129 | SMSG("tcp leave"); 130 | gsm_tcp_leave(gsmmng_tcp_leave_cb); 131 | break; 132 | 133 | case GSMMNG_STATE_TCP_CON_DELAY: 134 | SMSG("con delay"); 135 | if(systick_elaps(gsmmng_timestamp) > GSMMNG_TCP_CON_DELAY) { 136 | gsmmng_state = GSMMNG_STATE_TCP_CON; 137 | } 138 | break; 139 | 140 | case GSMMNG_STATE_TCP_CON: 141 | SMSG("tcp con"); 142 | gsm_tcp_con(last_ip, last_port, gsmmng_tcp_con_cb); 143 | gsmmng_state = GSMMNG_STATE_WAIT; 144 | break; 145 | 146 | case GSMMNG_STATE_WAIT: 147 | SMSG("wait..."); 148 | break; 149 | 150 | case GSMMNG_STATE_RETRY: 151 | SMSG("retry..."); 152 | if(systick_elaps(gsmmng_timestamp) > GSMMNG_RETRY_WAIT) { 153 | gsmmng_state = GSMMNG_STATE_NETW_CON; 154 | } 155 | break; 156 | 157 | case GSMMNG_STATE_IDLE: 158 | break; 159 | 160 | case GSMMNG_STATE_READY: 161 | break; 162 | } 163 | 164 | } 165 | 166 | static void gsmmng_netw_leave(gsm_state_t state, const char * txt) 167 | { 168 | if(state == GSM_STATE_OK) { 169 | gsmmng_state = GSMMNG_STATE_NETW_CON; 170 | } else { 171 | gsmmng_state = GSMMNG_STATE_RETRY; 172 | } 173 | } 174 | 175 | static void gsmmng_netw_con_cb(gsm_state_t state, const char * txt) 176 | { 177 | if(state == GSM_STATE_OK) { 178 | gsmmng_timestamp = systick_get(); 179 | gsmmng_state = GSMMNG_STATE_TCP_CON_DELAY; 180 | } else { 181 | gsmmng_timestamp = systick_get(); 182 | gsmmng_state = GSMMNG_STATE_RETRY; 183 | } 184 | } 185 | 186 | static void gsmmng_tcp_leave_cb(gsm_state_t state, const char * txt) 187 | { 188 | /*Unconditionally go to TCP connect*/ 189 | gsmmng_state = GSMMNG_STATE_TCP_CON; 190 | } 191 | 192 | static void gsmmng_tcp_con_cb(gsm_state_t state, const char * txt) 193 | { 194 | if(state == GSM_STATE_OK) { 195 | gsmmng_state = GSMMNG_STATE_READY; 196 | } else { 197 | gsmmng_timestamp = systick_get(); 198 | gsmmng_state = GSMMNG_STATE_RETRY; 199 | } 200 | } 201 | 202 | #endif /*USE_GSMMNG != 0*/ -------------------------------------------------------------------------------- /comm/gsmmng.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file gsmmng.h 3 | * 4 | */ 5 | 6 | #ifndef GSMMNG_H 7 | #define GSMMNG_H 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | 14 | /********************* 15 | * INCLUDES 16 | *********************/ 17 | #include "misc_conf.h" 18 | #if USE_GSMMNG != 0 19 | 20 | /********************* 21 | * DEFINES 22 | *********************/ 23 | 24 | /********************** 25 | * TYPEDEFS 26 | **********************/ 27 | typedef enum 28 | { 29 | GSMMNG_STATE_IDLE, 30 | GSMMNG_STATE_NETW_LEAVE, 31 | GSMMNG_STATE_NETW_CON, 32 | GSMMNG_STATE_TCP_CON_DELAY, 33 | GSMMNG_STATE_TCP_LEAVE, 34 | GSMMNG_STATE_TCP_CON, 35 | GSMMNG_STATE_WAIT, 36 | GSMMNG_STATE_RETRY, 37 | GSMMNG_STATE_READY, 38 | }gsmmng_state_t; 39 | 40 | 41 | /********************** 42 | * GLOBAL PROTOTYPES 43 | **********************/ 44 | void gsmmng_init(void); 45 | 46 | void gsmmng_set_last_apn(const char * apn); 47 | void gsmmng_set_last_tcp(const char * ip, const char * port); 48 | 49 | void gsmmng_reconnect(void); 50 | 51 | const char * gsmmng_get_last_apn(void); 52 | const char * gsmmng_get_last_ip(void); 53 | const char * gsmmng_get_last_port(void); 54 | 55 | gsmmng_state_t gsmmng_get_state(void); 56 | 57 | /********************** 58 | * MACROS 59 | **********************/ 60 | 61 | #endif /*USE_GSMMNG != 0*/ 62 | 63 | #ifdef __cplusplus 64 | } /* extern "C" */ 65 | #endif 66 | 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /comm/wifimng.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file wifimng.c 3 | * 4 | */ 5 | 6 | #include "wifimng.h" 7 | #if USE_WIFIMNG != 0 8 | 9 | #include 10 | #include "hal/wifi/wifi.h" 11 | #include "hal/systick/systick.h" 12 | #include "../os/ptask.h" 13 | 14 | /********************* 15 | * INCLUDES 16 | *********************/ 17 | 18 | /********************* 19 | * DEFINES 20 | *********************/ 21 | 22 | /********************** 23 | * TYPEDEFS 24 | **********************/ 25 | 26 | /********************** 27 | * STATIC PROTOTYPES 28 | **********************/ 29 | 30 | /********************** 31 | * STATIC VARIABLES 32 | **********************/ 33 | 34 | static wifimng_state_t wifimng_state; 35 | static uint32_t wifimng_timestamp = 0; 36 | static char last_ssid[64]; 37 | static char last_pwd[64]; 38 | static char last_ip[32]; 39 | static char last_port[16]; 40 | 41 | static void wifimng_task(void * param); 42 | static void wifimng_netw_ssid_cb(wifi_state_t state, const char * txt); 43 | static void wifimng_netw_con_cb(wifi_state_t state, const char * txt); 44 | static void wifimng_tcp_leave_cb(wifi_state_t state, const char * txt); 45 | static void wifimng_tcp_con_cb(wifi_state_t state, const char * txt); 46 | 47 | /********************** 48 | * MACROS 49 | **********************/ 50 | 51 | /********************** 52 | * GLOBAL FUNCTIONS 53 | **********************/ 54 | void wifimng_init(void) 55 | { 56 | wifimng_state = WIFIMNG_STATE_IDLE; 57 | ptask_create(wifimng_task, 1000, PTASK_PRIO_LOW, NULL); 58 | } 59 | 60 | 61 | void wifimng_set_last_netw(const char * ssid, const char * pwd) 62 | { 63 | strcpy(last_ssid, ssid); 64 | strcpy(last_pwd, pwd); 65 | wifimng_state = WIFIMNG_STATE_NETW_TEST; 66 | } 67 | 68 | void wifimng_set_last_tcp(const char * ip, const char * port) 69 | { 70 | strcpy(last_ip, ip); 71 | strcpy(last_port, port); 72 | wifimng_state = WIFIMNG_STATE_NETW_TEST; 73 | } 74 | 75 | wifimng_state_t wifimng_get_state(void) 76 | { 77 | return wifimng_state; 78 | } 79 | 80 | void wifimng_reconnect(void) 81 | { 82 | wifimng_state = WIFIMNG_STATE_NETW_TEST; 83 | } 84 | 85 | const char * wifimng_get_last_ssid(void) 86 | { 87 | return last_ssid; 88 | } 89 | 90 | const char * wifimng_get_last_pwd(void) 91 | { 92 | return last_ssid; 93 | } 94 | 95 | const char * wifimng_get_last_ip(void) 96 | { 97 | return last_ip; 98 | } 99 | 100 | const char * wifimng_get_last_port(void) 101 | { 102 | return last_port; 103 | } 104 | 105 | 106 | /********************** 107 | * STATIC FUNCTIONS 108 | **********************/ 109 | 110 | static void wifimng_task(void * param) 111 | { 112 | 113 | if(last_ssid[0] == '\0' || last_pwd[0] == '\0' || last_ip[0] == '\0' || last_port[0] == '\0') { 114 | return; 115 | } 116 | 117 | switch(wifimng_state) { 118 | 119 | case WIFIMNG_STATE_NETW_TEST: 120 | if(wifi_busy() != false) break; 121 | 122 | wifi_netw_get_ssid(wifimng_netw_ssid_cb); 123 | wifimng_state = WIFIMNG_STATE_WAIT; 124 | break; 125 | 126 | 127 | case WIFIMNG_STATE_NETW_CON: 128 | wifi_netw_con(last_ssid, last_pwd, wifimng_netw_con_cb); 129 | wifimng_state = WIFIMNG_STATE_WAIT; 130 | break; 131 | 132 | 133 | case WIFIMNG_STATE_TCP_LEAVE: 134 | wifi_tcp_leave(wifimng_tcp_leave_cb); 135 | break; 136 | 137 | case WIFIMNG_STATE_TCP_CON_DELAY: 138 | if(systick_elaps(wifimng_timestamp) > WIFIMNG_TCP_CON_DELAY) { 139 | wifimng_state = WIFIMNG_STATE_TCP_CON; 140 | } 141 | break; 142 | 143 | case WIFIMNG_STATE_TCP_CON: 144 | wifi_tcp_con(last_ip, last_port, wifimng_tcp_con_cb); 145 | wifimng_state = WIFIMNG_STATE_WAIT; 146 | break; 147 | 148 | case WIFIMNG_STATE_WAIT: 149 | break; 150 | 151 | case WIFIMNG_STATE_RETRY: 152 | if(systick_elaps(wifimng_timestamp) > WIFIMNG_RETRY_WAIT) { 153 | wifimng_state = WIFIMNG_STATE_NETW_CON; 154 | } 155 | break; 156 | case WIFIMNG_STATE_READY: 157 | break; 158 | case WIFIMNG_STATE_IDLE: 159 | break; 160 | } 161 | 162 | } 163 | 164 | static void wifimng_netw_ssid_cb(wifi_state_t state, const char * txt) 165 | { 166 | if(state == WIFI_STATE_OK) { 167 | if(txt[0] == '\0') { 168 | wifimng_state = WIFIMNG_STATE_NETW_CON; 169 | } else { 170 | wifimng_state = WIFIMNG_STATE_TCP_LEAVE; 171 | } 172 | } else { 173 | wifimng_state = WIFIMNG_STATE_NETW_CON; 174 | } 175 | } 176 | 177 | static void wifimng_netw_con_cb(wifi_state_t state, const char * txt) 178 | { 179 | if(state == WIFI_STATE_OK) { 180 | wifimng_timestamp = systick_get(); 181 | wifimng_state = WIFIMNG_STATE_TCP_CON_DELAY; 182 | } else { 183 | wifimng_timestamp = systick_get(); 184 | wifimng_state = WIFIMNG_STATE_RETRY; 185 | } 186 | } 187 | 188 | static void wifimng_tcp_leave_cb(wifi_state_t state, const char * txt) 189 | { 190 | /*Unconditionally go to TCP connect*/ 191 | wifimng_state = WIFIMNG_STATE_TCP_CON; 192 | } 193 | 194 | static void wifimng_tcp_con_cb(wifi_state_t state, const char * txt) 195 | { 196 | if(state == WIFI_STATE_OK) { 197 | wifimng_state = WIFIMNG_STATE_READY; 198 | } else { 199 | wifimng_timestamp = systick_get(); 200 | wifimng_state = WIFIMNG_STATE_RETRY; 201 | } 202 | } 203 | 204 | #endif 205 | -------------------------------------------------------------------------------- /comm/wifimng.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file templ.h 3 | * 4 | */ 5 | 6 | #ifndef WIFIMNG_H 7 | #define WIFIMNG_H 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | 14 | /********************* 15 | * INCLUDES 16 | *********************/ 17 | #include "../../misc_conf.h" 18 | #if USE_WIFIMNG != 0 19 | 20 | /********************* 21 | * DEFINES 22 | *********************/ 23 | 24 | /********************** 25 | * TYPEDEFS 26 | **********************/ 27 | typedef enum 28 | { 29 | WIFIMNG_STATE_IDLE, 30 | WIFIMNG_STATE_NETW_TEST, 31 | WIFIMNG_STATE_NETW_CON, 32 | WIFIMNG_STATE_TCP_CON_DELAY, 33 | WIFIMNG_STATE_TCP_LEAVE, 34 | WIFIMNG_STATE_TCP_CON, 35 | WIFIMNG_STATE_WAIT, 36 | WIFIMNG_STATE_RETRY, 37 | WIFIMNG_STATE_READY, 38 | }wifimng_state_t; 39 | 40 | 41 | /********************** 42 | * GLOBAL PROTOTYPES 43 | **********************/ 44 | void wifimng_init(void); 45 | 46 | void wifimng_set_last_netw(const char * ssid, const char * pwd); 47 | void wifimng_set_last_tcp(const char * ip, const char * port); 48 | 49 | void wifimng_reconnect(void); 50 | 51 | const char * wifimng_get_last_ssid(void) ; 52 | const char * wifimng_get_last_pwd(void) ; 53 | const char * wifimng_get_last_ip(void) ; 54 | const char * wifimng_get_last_port(void); 55 | 56 | wifimng_state_t wifimng_get_state(void); 57 | 58 | /********************** 59 | * MACROS 60 | **********************/ 61 | 62 | #endif 63 | 64 | #ifdef __cplusplus 65 | } /* extern "C" */ 66 | #endif 67 | 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /fs/fat32/fat32.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file fat32.h 3 | * Functions to give an API to a Fat32 storage device which is compatible 4 | * with the fs_int module. 5 | */ 6 | 7 | #ifndef FAT32_H 8 | #define FAT32_H 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | 15 | /********************* 16 | * INCLUDES 17 | *********************/ 18 | #include "../../../misc_conf.h" 19 | #if USE_FAT32 != 0 20 | 21 | #include "../fsint.h" 22 | 23 | /********************* 24 | * DEFINES 25 | *********************/ 26 | 27 | /********************** 28 | * TYPEDEFS 29 | **********************/ 30 | 31 | /********************** 32 | * GLOBAL PROTOTYPES 33 | **********************/ 34 | 35 | /** 36 | * Create a driver for the fat32 device and initilaize it. 37 | */ 38 | void fat32_init(void); 39 | 40 | /** 41 | * Give the state of the fat32 storage device 42 | * @return true if the device is initialized and can be used else false 43 | */ 44 | bool fat32_ready(void); 45 | 46 | /** 47 | * Open a file 48 | * @param file_p pointer to a FIL type variable 49 | * @param path path of the file (e.g. "dir1/dir2/file1.txt") 50 | * @param mode open mode (FS_MODE_RD or FS_MODE_WR or both with | (or connection)) 51 | * @return FS_RES_OK or any error from 'fs_res_t' 52 | */ 53 | fs_res_t fat32_open (void * file_p, const char * path, fs_mode_t mode); 54 | 55 | /** 56 | * Close an already opened file 57 | * @param file_p pointer to a FIL type variable 58 | * @return FS_RES_OK or any error from fs_res_t 59 | */ 60 | fs_res_t fat32_close (void * file_p); 61 | 62 | /** 63 | * Remove (delete) a file 64 | * @param path the path of the file ("dir1/file1.txt") 65 | * @return FS_RES_OK or any error from 'fs_res_t' 66 | */ 67 | fs_res_t fat32_remove(const char * path); 68 | 69 | /** 70 | * Read data from an opened file 71 | * @param file_p pointer to a FIL type variable 72 | * @param buf pointer a buffer to store the read bytes 73 | * @param btr the number of Bytes To Read 74 | * @param br the number of real read bytes (Bytes Read) 75 | * @return FS_RES_OK or any error from 'fs_res_t' 76 | */ 77 | fs_res_t fat32_read (void * file_p, void * buf, uint32_t btr, uint32_t * br); 78 | 79 | /** 80 | * Write data to an opened file 81 | * @param file_p pointer to a FIL type variable 82 | * @param buf pointer to buffer where the data to write is located 83 | * @param btw the number of Bytes To Write 84 | * @param bw the number of real written bytes (Bytes Written) 85 | * @return FS_RES_OK or any error from 'fs_res_t' 86 | */ 87 | fs_res_t fat32_write (void * file_p, const void * buf, uint32_t btw, uint32_t * bw); 88 | 89 | /** 90 | * Position the read write pointer to given position 91 | * @param file_p pointer to a FIL type variable 92 | * @param pos the new position expressed in bytes index (0: start of file) 93 | * @return FS_RES_OK or any error from 'fs_res_t' 94 | */ 95 | fs_res_t fat32_seek (void * file_p, uint32_t pos); 96 | 97 | /** 98 | * Give the position of the read write pointer 99 | * @param file_p pointer to a FIL type variable 100 | * @param pos_p pointer to store the position of the read write pointer 101 | * @return FS_RES_OK or any error from 'fs_res_t' 102 | */ 103 | fs_res_t fat32_tell (void * file_p, uint32_t * pos_p); 104 | 105 | /** 106 | * Truncate the file size to the current position of read write pointer 107 | * @param file_p pointer to a FIL type variable 108 | * @return FS_RES_OK or any error from 'fs_res_t' 109 | */ 110 | fs_res_t fat32_trunc (void * file_p); 111 | 112 | /** 113 | * Give the size of a file 114 | * @param file_p pointer to a FIL type variable 115 | * @param size_p pointer to store the size 116 | * @return FS_RES_OK or any error from 'fs_res_t' 117 | */ 118 | fs_res_t fat32_size (void * file_p, uint32_t * size_p); 119 | 120 | /** 121 | * Initialize a variable for directory reading 122 | * @param rddir_p pointer to a 'DIR' variable 123 | * @param path path to a directory 124 | * @return FS_RES_OK or any error from fs_res_t enum 125 | */ 126 | fs_res_t fat32_readdir_init(void * rddir_p, const char * path); 127 | 128 | /** 129 | * Read the next filename form a directory. 130 | * The name of the directories will begin with '/' 131 | * @param rddir_p pointer to an initialized 'DIR' variable 132 | * @param fn pointer to a buffer to store the filename 133 | * @return FS_RES_OK or any error from fs_res_t enum 134 | */ 135 | fs_res_t fat32_readdir(void * rddir_p, char * fn); 136 | 137 | /** 138 | * Close the directory reading 139 | * @param rddir_p pointer to an initialized 'DIR' variable 140 | * @return FS_RES_OK or any error from fs_res_t enum 141 | */ 142 | fs_res_t fat32_readdir_close(void * rddir_p); 143 | 144 | /** 145 | * Give the size of a drive 146 | * @param total_p pointer to store the total size [kB] 147 | * @param free_p pointer to store the free size [kB] 148 | * @return FS_RES_OK or any error from 'fs_res_t' 149 | */ 150 | fs_res_t fat32_free (uint32_t * total_p, uint32_t * free_p) 151 | 152 | /********************** 153 | * MACROS 154 | **********************/ 155 | 156 | #endif 157 | 158 | #ifdef __cplusplus 159 | } /* extern "C" */ 160 | #endif 161 | 162 | 163 | #endif 164 | -------------------------------------------------------------------------------- /fs/fat32/fat32_readme.txt: -------------------------------------------------------------------------------- 1 | This is the well known FatFS from http://elm-chan.org/fsw/ff/00index_e.html 2 | -------------------------------------------------------------------------------- /fs/fat32/integer.h: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------*/ 2 | /* Integer type definitions for FatFs module */ 3 | /*-------------------------------------------*/ 4 | 5 | #ifndef _FF_INTEGER 6 | #define _FF_INTEGER 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | 13 | #ifdef _WIN32 /* Development platform */ 14 | 15 | #include 16 | #include 17 | 18 | #else /* Embedded platform */ 19 | 20 | /* This type MUST be 8-bit */ 21 | typedef unsigned char BYTE; 22 | 23 | /* These types MUST be 16-bit */ 24 | typedef short SHORT; 25 | typedef unsigned short WORD; 26 | typedef unsigned short WCHAR; 27 | 28 | /* These types MUST be 16-bit or 32-bit */ 29 | typedef int INT; 30 | typedef unsigned int UINT; 31 | 32 | /* These types MUST be 32-bit */ 33 | typedef long LONG; 34 | typedef unsigned long DWORD; 35 | 36 | #endif 37 | 38 | #ifdef __cplusplus 39 | } /* extern "C" */ 40 | #endif 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /fs/fat32/option/syscall.c: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------*/ 2 | /* Sample code of OS dependent controls for FatFs */ 3 | /* (C)ChaN, 2014 */ 4 | /*------------------------------------------------------------------------*/ 5 | 6 | #include "../../../../misc_conf.h" 7 | #if USE_FAT32 != 0 8 | 9 | #include "../ff.h" 10 | 11 | 12 | #if _FS_REENTRANT 13 | /*------------------------------------------------------------------------*/ 14 | /* Create a Synchronization Object */ 15 | /*------------------------------------------------------------------------*/ 16 | /* This function is called in f_mount() function to create a new 17 | / synchronization object, such as semaphore and mutex. When a 0 is returned, 18 | / the f_mount() function fails with FR_INT_ERR. 19 | */ 20 | 21 | int ff_cre_syncobj ( /* !=0:Function succeeded, ==0:Could not create due to any error */ 22 | BYTE vol, /* Corresponding logical drive being processed */ 23 | _SYNC_t *sobj /* Pointer to return the created sync object */ 24 | ) 25 | { 26 | int ret; 27 | 28 | 29 | *sobj = CreateMutex(NULL, FALSE, NULL); /* Win32 */ 30 | ret = (int)(*sobj != INVALID_HANDLE_VALUE); 31 | 32 | // *sobj = SyncObjects[vol]; /* uITRON (give a static created sync object) */ 33 | // ret = 1; /* The initial value of the semaphore must be 1. */ 34 | 35 | // *sobj = OSMutexCreate(0, &err); /* uC/OS-II */ 36 | // ret = (int)(err == OS_NO_ERR); 37 | 38 | // *sobj = xSemaphoreCreateMutex(); /* FreeRTOS */ 39 | // ret = (int)(*sobj != NULL); 40 | 41 | return ret; 42 | } 43 | 44 | 45 | 46 | /*------------------------------------------------------------------------*/ 47 | /* Delete a Synchronization Object */ 48 | /*------------------------------------------------------------------------*/ 49 | /* This function is called in f_mount() function to delete a synchronization 50 | / object that created with ff_cre_syncobj function. When a 0 is returned, 51 | / the f_mount() function fails with FR_INT_ERR. 52 | */ 53 | 54 | int ff_del_syncobj ( /* !=0:Function succeeded, ==0:Could not delete due to any error */ 55 | _SYNC_t sobj /* Sync object tied to the logical drive to be deleted */ 56 | ) 57 | { 58 | int ret; 59 | 60 | 61 | ret = CloseHandle(sobj); /* Win32 */ 62 | 63 | // ret = 1; /* uITRON (nothing to do) */ 64 | 65 | // OSMutexDel(sobj, OS_DEL_ALWAYS, &err); /* uC/OS-II */ 66 | // ret = (int)(err == OS_NO_ERR); 67 | 68 | // vSemaphoreDelete(sobj); /* FreeRTOS */ 69 | // ret = 1; 70 | 71 | return ret; 72 | } 73 | 74 | 75 | 76 | /*------------------------------------------------------------------------*/ 77 | /* Request Grant to Access the Volume */ 78 | /*------------------------------------------------------------------------*/ 79 | /* This function is called on entering file functions to lock the volume. 80 | / When a 0 is returned, the file function fails with FR_TIMEOUT. 81 | */ 82 | 83 | int ff_req_grant ( /* 1:Got a grant to access the volume, 0:Could not get a grant */ 84 | _SYNC_t sobj /* Sync object to wait */ 85 | ) 86 | { 87 | int ret; 88 | 89 | ret = (int)(WaitForSingleObject(sobj, _FS_TIMEOUT) == WAIT_OBJECT_0); /* Win32 */ 90 | 91 | // ret = (int)(wai_sem(sobj) == E_OK); /* uITRON */ 92 | 93 | // OSMutexPend(sobj, _FS_TIMEOUT, &err)); /* uC/OS-II */ 94 | // ret = (int)(err == OS_NO_ERR); 95 | 96 | // ret = (int)(xSemaphoreTake(sobj, _FS_TIMEOUT) == pdTRUE); /* FreeRTOS */ 97 | 98 | return ret; 99 | } 100 | 101 | 102 | 103 | /*------------------------------------------------------------------------*/ 104 | /* Release Grant to Access the Volume */ 105 | /*------------------------------------------------------------------------*/ 106 | /* This function is called on leaving file functions to unlock the volume. 107 | */ 108 | 109 | void ff_rel_grant ( 110 | _SYNC_t sobj /* Sync object to be signaled */ 111 | ) 112 | { 113 | ReleaseMutex(sobj); /* Win32 */ 114 | 115 | // sig_sem(sobj); /* uITRON */ 116 | 117 | // OSMutexPost(sobj); /* uC/OS-II */ 118 | 119 | // xSemaphoreGive(sobj); /* FreeRTOS */ 120 | } 121 | 122 | #endif 123 | 124 | 125 | 126 | 127 | #if _USE_LFN == 3 /* LFN with a working buffer on the heap */ 128 | /*------------------------------------------------------------------------*/ 129 | /* Allocate a memory block */ 130 | /*------------------------------------------------------------------------*/ 131 | /* If a NULL is returned, the file function fails with FR_NOT_ENOUGH_CORE. 132 | */ 133 | 134 | void* ff_memalloc ( /* Returns pointer to the allocated memory block */ 135 | UINT msize /* Number of bytes to allocate */ 136 | ) 137 | { 138 | return malloc(msize); /* Allocate a new memory block with POSIX API */ 139 | } 140 | 141 | 142 | /*------------------------------------------------------------------------*/ 143 | /* Free a memory block */ 144 | /*------------------------------------------------------------------------*/ 145 | 146 | void ff_memfree ( 147 | void* mblock /* Pointer to the memory block to free */ 148 | ) 149 | { 150 | free(mblock); /* Discard the memory block with POSIX API */ 151 | } 152 | 153 | #endif 154 | #endif /*USE_FAT32 != 0*/ 155 | -------------------------------------------------------------------------------- /fs/fsint.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file fsint.h 3 | * 4 | */ 5 | 6 | #ifndef FSINT_H 7 | #define FSINT_H 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | 14 | /********************* 15 | * INCLUDES 16 | *********************/ 17 | #include "../../misc_conf.h" 18 | #if USE_FSINT != 0 19 | 20 | #include 21 | #include 22 | #include "../mem/dyn_mem.h" 23 | 24 | /********************* 25 | * DEFINES 26 | *********************/ 27 | #define FSINT_MAX_FN_LENGTH 64 28 | 29 | /********************** 30 | * TYPEDEFS 31 | **********************/ 32 | typedef enum 33 | { 34 | FS_RES_OK = 0, 35 | FS_RES_HW_ERR, /*Low level hardwer error*/ 36 | FS_RES_FS_ERR, /*Error in the file system structure */ 37 | FS_RES_NOT_EX, /*Driver, file or direcory is not exists*/ 38 | FS_RES_FULL, /*Disk full*/ 39 | FS_RES_LOCKED, /*The file is already opened*/ 40 | FS_RES_DENIED, /*Access denied. Check 'fs_open' modes and write protect*/ 41 | FS_BUSY, /*The filesystem now can't handle it, try later*/ 42 | FS_RES_TOUT, /*Process timeouted*/ 43 | FS_RES_NOT_IMP, /*Requested function is not implemented*/ 44 | FS_RES_OUT_OF_MEM, /*Not enough memory for an internal opretion*/ 45 | FS_RES_INV_PARAM, /*Invalid parameter among arguments*/ 46 | FS_RES_UNKNOWN, /*Other unknown error*/ 47 | }fs_res_t; 48 | 49 | struct __fs_drv_struct; 50 | 51 | typedef struct 52 | { 53 | void * file_d; 54 | struct __fs_drv_struct* drv; 55 | }fs_file_t; 56 | 57 | 58 | typedef struct 59 | { 60 | void * rddir_d; 61 | struct __fs_drv_struct * drv; 62 | }fs_readdir_t; 63 | 64 | typedef enum 65 | { 66 | FS_MODE_WR = 0x01, 67 | FS_MODE_RD = 0x02, 68 | }fs_mode_t; 69 | 70 | typedef struct __fs_drv_struct 71 | { 72 | char letter; 73 | uint16_t file_size; 74 | uint16_t rddir_size; 75 | bool (*ready) (void); 76 | 77 | fs_res_t (*open) (void * file_p, const char * path, fs_mode_t mode); 78 | fs_res_t (*close) (void * file_p); 79 | fs_res_t (*remove) (const char * fn); 80 | fs_res_t (*read) (void * file_p, void * buf, uint32_t btr, uint32_t * br); 81 | fs_res_t (*write) (void * file_p, const void * buf, uint32_t btw, uint32_t * bw); 82 | fs_res_t (*seek) (void * file_p, uint32_t pos); 83 | fs_res_t (*tell) (void * file_p, uint32_t * pos_p); 84 | fs_res_t (*trunc) (void * file_p); 85 | fs_res_t (*size) (void * file_p, uint32_t * size_p); 86 | fs_res_t (*free) (uint32_t * total_p, uint32_t * free_p); 87 | 88 | fs_res_t (*rddir_init) (void * rddir_p, const char * path); 89 | fs_res_t (*rddir) (void * rddir_p, char * fn); 90 | fs_res_t (*rddir_close) (void * rddir_p); 91 | }fs_drv_t; 92 | 93 | /********************** 94 | * GLOBAL PROTOTYPES 95 | **********************/ 96 | 97 | /** 98 | * Initialize the File system interface 99 | */ 100 | void fs_init(void); 101 | 102 | /** 103 | * Add a new drive 104 | * @param drv_p pointer to an fs_drv_t structure which is inited with the 105 | * corresponding function pointer 106 | */ 107 | void fs_add_drv(fs_drv_t * drv_p); 108 | 109 | /** 110 | * Open a file 111 | * @param file_p pointer to a fs_file_t variable 112 | * @param path path to the file beginning with the driver letter (e.g. S:/folder/file.txt) 113 | * @param mode read: FS_MODE_RD, write: FS_MODE_WR, both: FS_MODE_RD | FS_MODE_WR 114 | * @return FS_RES_OK or any error from fs_res_t enum 115 | */ 116 | fs_res_t fs_open (fs_file_t * file_p, const char * path, fs_mode_t mode); 117 | 118 | /** 119 | * Close an already opened file 120 | * @param file_p pointer to a fs_file_t variable 121 | * @return FS_RES_OK or any error from fs_res_t enum 122 | */ 123 | fs_res_t fs_close (fs_file_t * file_p); 124 | 125 | /** 126 | * Delete a file 127 | * @param path path of the file to delete 128 | * @return FS_RES_OK or any error from fs_res_t enum 129 | */ 130 | fs_res_t fs_remove (const char * path); 131 | 132 | /** 133 | * Read from a file 134 | * @param file_p pointer to a fs_file_t variable 135 | * @param buf pointer to a buffer where the read bytes are stored 136 | * @param btr Bytes To Read 137 | * @param br the number of real read bytes (Bytes Read). NULL if unused. 138 | * @return FS_RES_OK or any error from fs_res_t enum 139 | */ 140 | fs_res_t fs_read (fs_file_t * file_p, void * buf, uint32_t btr, uint32_t * br); 141 | 142 | /** 143 | * Write into a file 144 | * @param file_p pointer to a fs_file_t variable 145 | * @param buf pointer to a buffer with the bytes to write 146 | * @param btr Bytes To Write 147 | * @param br the number of real written bytes (Bytes Written). NULL if unused. 148 | * @return FS_RES_OK or any error from fs_res_t enum 149 | */ 150 | fs_res_t fs_write (fs_file_t * file_p, const void * buf, uint32_t btw, uint32_t * bw); 151 | 152 | /** 153 | * Set the position of the 'cursor' (read write pointer) in a file 154 | * @param file_p pointer to a fs_file_t variable 155 | * @param pos the new position expressed in bytes index (0: start of file) 156 | * @return FS_RES_OK or any error from fs_res_t enum 157 | */ 158 | fs_res_t fs_seek (fs_file_t * file_p, uint32_t pos); 159 | 160 | /** 161 | * Give the position of the read write pointer 162 | * @param file_p pointer to a fs_file_t variable 163 | * @param pos_p pointer to store the position of the read write pointer 164 | * @return FS_RES_OK or any error from 'fs_res_t' 165 | */ 166 | fs_res_t fs_tell (fs_file_t * file_p, uint32_t * pos); 167 | 168 | /** 169 | * Give the size of a file bytes 170 | * @param file_p pointer to a fs_file_t variable 171 | * @param size pointer to a variable to store the size 172 | * @return FS_RES_OK or any error from fs_res_t enum 173 | */ 174 | fs_res_t fs_size (fs_file_t * file_p, uint32_t * size); 175 | 176 | /** 177 | * Initialize a 'fs_read_dir_t' variable for directory reading 178 | * @param rddir_p pointer to a 'fs_read_dir_t' variable 179 | * @param path path to a directory 180 | * @return FS_RES_OK or any error from fs_res_t enum 181 | */ 182 | fs_res_t fs_readdir_init(fs_readdir_t * rddir_p, const char * path); 183 | 184 | /** 185 | * Read the next filename form a directory. 186 | * The name of the directories will begin with '/' 187 | * @param rddir_p pointer to an initialized 'fs_read_dir_t' variable 188 | * @param fn pointer to a buffer to store the filename 189 | * @return FS_RES_OK or any error from fs_res_t enum 190 | */ 191 | fs_res_t fs_readdir (fs_readdir_t * rddir_p, char * fn); 192 | 193 | /** 194 | * Close the directory reading 195 | * @param rddir_p pointer to an initialized 'fs_read_dir_t' variable 196 | * @return FS_RES_OK or any error from fs_res_t enum 197 | */ 198 | fs_res_t fs_readdir_close (fs_readdir_t * rddir_p); 199 | 200 | /** 201 | * Get the free and total size of a driver in kB 202 | * @param letter the driver letter 203 | * @param total_p pointer to store the total size [kB] 204 | * @param free_p pointer to store the free size [kB] 205 | * @return FS_RES_OK or any error from fs_res_t enum 206 | */ 207 | fs_res_t fs_free (char letter, uint32_t * total_p, uint32_t * free_p); 208 | 209 | /** 210 | * Fill a buffer with the letters of existing drivers 211 | * @param buf buffer to store the letters ('\0' added after the last letter) 212 | * @return the buffer 213 | */ 214 | char * fs_get_letters(char * buf); 215 | 216 | /** 217 | * Return with the extension of the filename 218 | * @param fn string with a filename 219 | * @return pointer to the beginning extension or empty string if no extension 220 | */ 221 | const char * fs_get_ext(const char * fn); 222 | 223 | /** 224 | * Step up one level 225 | * @param path pointer to a file name 226 | * @return the truncated file name 227 | */ 228 | char * fs_up(char * path); 229 | 230 | /** 231 | * Get the last element of a path (e.g. U:/folder/file -> file) 232 | * @param buf buffer to store the letters ('\0' added after the last letter) 233 | * @return pointer to the beginning of the last element in the path 234 | */ 235 | const char * fs_get_last(const char * path); 236 | 237 | /********************** 238 | * MACROS 239 | **********************/ 240 | 241 | #endif 242 | 243 | #ifdef __cplusplus 244 | } /* extern "C" */ 245 | #endif 246 | 247 | 248 | #endif 249 | -------------------------------------------------------------------------------- /fs/linuxfs/linuxfs.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file linuxfs.c 3 | * Functions to give an API to the standard 4 | * file operation functions to be compatible 5 | */ 6 | 7 | /********************* 8 | * INCLUDES 9 | *********************/ 10 | #include "../../../misc_conf.h" 11 | #if USE_LINUXFS != 0 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include "linuxfs.h" 20 | 21 | /********************* 22 | * DEFINES 23 | *********************/ 24 | 25 | /********************** 26 | * TYPEDEFS 27 | **********************/ 28 | 29 | /********************** 30 | * STATIC PROTOTYPES 31 | **********************/ 32 | static fs_res_t linuxfs_res_trans(int linuxfs_res); 33 | 34 | /********************** 35 | * STATIC VARIABLES 36 | **********************/ 37 | 38 | /********************** 39 | * MACROS 40 | **********************/ 41 | 42 | /********************** 43 | * GLOBAL FUNCTIONS 44 | **********************/ 45 | /** 46 | * Create a driver for the linuxfs device and initilaize it. 47 | */ 48 | void linuxfs_init(void) 49 | { 50 | /*Create the driver*/ 51 | fs_drv_t linux_drv; 52 | memset(&linux_drv, 0, sizeof(fs_drv_t)); /*Initialization*/ 53 | 54 | linux_drv.file_size = sizeof(FILE *); 55 | linux_drv.rddir_size = sizeof(DIR *); 56 | linux_drv.letter = LINUXFS_LETTER; 57 | linux_drv.ready = linuxfs_ready; 58 | 59 | linux_drv.open = linuxfs_open; 60 | linux_drv.close = linuxfs_close; 61 | linux_drv.remove = linuxfs_remove; 62 | linux_drv.read = linuxfs_read; 63 | linux_drv.write = linuxfs_write; 64 | linux_drv.seek = linuxfs_seek; 65 | linux_drv.tell = linuxfs_tell; 66 | linux_drv.size = linuxfs_size; 67 | linux_drv.trunc = NULL; 68 | 69 | linux_drv.rddir_init = linuxfs_readdir_init; 70 | linux_drv.rddir = linuxfs_readdir; 71 | linux_drv.rddir_close = linuxfs_readdir_close; 72 | 73 | linux_drv.free = NULL; 74 | fs_add_drv(&linux_drv); 75 | } 76 | 77 | /** 78 | * Give the state of the linuxfs 79 | * @return true if it is already initialized 80 | */ 81 | bool linuxfs_ready(void) 82 | { 83 | return true; 84 | } 85 | 86 | /** 87 | * Open a file 88 | * @param file_p pointer to a FIL type variable 89 | * @param path path of the file (e.g. "dir1/dir2/file1.txt") 90 | * @param mode open mode (FS_MODE_RD or FS_MODE_WR or both with | (or connection)) 91 | * @return FS_RES_OK or any error from 'fs_res_t' 92 | */ 93 | fs_res_t linuxfs_open (void * file_p, const char * path, fs_mode_t mode) 94 | { 95 | FILE ** fp = file_p; 96 | 97 | errno = 0; 98 | const char * linuxfs_mode = 0; 99 | if(mode == FS_MODE_RD) linuxfs_mode = "r"; 100 | if(mode == FS_MODE_WR) linuxfs_mode = "a"; 101 | if(mode == (FS_MODE_WR | FS_MODE_RD)) linuxfs_mode = "a+"; 102 | 103 | *fp = fopen(path, linuxfs_mode); 104 | return linuxfs_res_trans(errno); 105 | } 106 | 107 | /** 108 | * Close an already opened file 109 | * @param file_p pointer to a FIL type variable 110 | * @return FS_RES_OK or any error from fs_res_t 111 | */ 112 | fs_res_t linuxfs_close (void * file_p) 113 | { 114 | FILE ** fp = file_p; 115 | if(*fp == NULL) return FS_RES_INV_PARAM; 116 | errno = 0; 117 | fclose(*fp); 118 | return linuxfs_res_trans(errno); 119 | } 120 | 121 | /** 122 | * Remove (delete) a file 123 | * @param path the path of the file ("dir1/file1.txt") 124 | * @return FS_RES_OK or any error from 'fs_res_t' 125 | */ 126 | fs_res_t linuxfs_remove(const char * path) 127 | { 128 | errno = 0; 129 | remove(path); 130 | return linuxfs_res_trans(errno); 131 | } 132 | 133 | /** 134 | * Read data from an opened file 135 | * @param file_p pointer to a FIL type variable 136 | * @param buf pointer a buffer to store the read bytes 137 | * @param btr the number of Bytes To Read 138 | * @param br the number of real read bytes (Bytes Read) 139 | * @return FS_RES_OK or any error from 'fs_res_t' 140 | */ 141 | fs_res_t linuxfs_read (void * file_p, void * buf, uint32_t btr, uint32_t * br) 142 | { 143 | FILE ** fp = file_p; 144 | if(*fp == NULL) return FS_RES_INV_PARAM; 145 | 146 | errno = 0; 147 | (*br) = fread(buf, 1, btr, *fp); 148 | return linuxfs_res_trans(errno); 149 | } 150 | 151 | /** 152 | * Write data to an opened file 153 | * @param file_p pointer to a FIL type variable 154 | * @param buf pointer to buffer where the data to write is located 155 | * @param btw the number of Bytes To Write 156 | * @param bw the number of real written bytes (Bytes Written) 157 | * @return FS_RES_OK or any error from 'fs_res_t' 158 | */ 159 | fs_res_t linuxfs_write (void * file_p, const void * buf, uint32_t btw, uint32_t * bw) 160 | { 161 | FILE ** fp = file_p; 162 | if(*fp == NULL) return FS_RES_INV_PARAM; 163 | 164 | errno = 0; 165 | (*bw) = fwrite(buf, 1, btw, *fp); 166 | return linuxfs_res_trans(errno); 167 | } 168 | 169 | /** 170 | * Position the read write pointer to given position 171 | * @param file_p pointer to a FIL type variable 172 | * @param pos the new position expressed in bytes index (0: start of file) 173 | * @return FS_RES_OK or any error from 'fs_res_t' 174 | */ 175 | fs_res_t linuxfs_seek (void * file_p, uint32_t pos) 176 | { 177 | FILE ** fp = file_p; 178 | if(*fp == NULL) return FS_RES_INV_PARAM; 179 | 180 | errno = 0; 181 | fseek(*fp, pos, SEEK_SET); 182 | return linuxfs_res_trans(errno); 183 | } 184 | 185 | /** 186 | * Give the position of the read write pointer 187 | * @param file_p pointer to a FIL type variable 188 | * @param pos_p pointer to store the position of the read write pointer 189 | * @return FS_RES_OK or any error from 'fs_res_t' 190 | */ 191 | fs_res_t linuxfs_tell (void * file_p, uint32_t * pos_p) 192 | { 193 | FILE ** fp = file_p; 194 | if(*fp == NULL) return FS_RES_INV_PARAM; 195 | 196 | errno = 0; 197 | long int x = ftell(*fp); 198 | if(x < 0) *pos_p = 0; 199 | else *pos_p = (uint32_t)x; 200 | 201 | return linuxfs_res_trans(errno); 202 | } 203 | 204 | 205 | /** 206 | * Give the size of a file 207 | * @param file_p pointer to a FIL type variable 208 | * @param size_p pointer to store the size 209 | * @return FS_RES_OK or any error from 'fs_res_t' 210 | */ 211 | fs_res_t linuxfs_size (void * file_p, uint32_t * size_p) 212 | { 213 | FILE ** fp = file_p; 214 | if(*fp == NULL) return FS_RES_INV_PARAM; 215 | 216 | errno = 0; 217 | /*Save the current position*/ 218 | long int ori = ftell(*fp); 219 | if(errno) return linuxfs_res_trans(errno); 220 | 221 | /* Seek to the and read the position. 222 | * It is equal to the size*/ 223 | fseek(*fp, 0, SEEK_END); 224 | if(errno) return linuxfs_res_trans(errno); 225 | long int x; 226 | x = ftell(*fp); 227 | if(errno) return linuxfs_res_trans(errno); 228 | 229 | *size_p = (uint32_t)x; 230 | 231 | /*Revert the position*/ 232 | fseek(*fp, ori, SEEK_SET); // seek back read write pointer 233 | 234 | return linuxfs_res_trans(errno); 235 | } 236 | 237 | 238 | /** 239 | * Initialize a variable for directory reading 240 | * @param rddir_p pointer to a 'DIR' variable 241 | * @param path path to a directory 242 | * @return FS_RES_OK or any error from fs_res_t enum 243 | */ 244 | fs_res_t linuxfs_readdir_init(void * rddir_p, const char * path) 245 | { 246 | errno = 0; 247 | char path_buf[512]; 248 | sprintf(path_buf,"%s%s" , LINUXFS_ROOT_DIR, path); 249 | 250 | DIR ** rd = rddir_p; 251 | *rd = opendir(path_buf); 252 | 253 | return linuxfs_res_trans(errno); 254 | } 255 | 256 | /** 257 | * Read the next filename form a directory. 258 | * The name of the directories will begin with '/' 259 | * @param rddir_p pointer to an initialized 'DIR' variable 260 | * @param fn pointer to a buffer to store the filename 261 | * @return FS_RES_OK or any error from fs_res_t enum 262 | */ 263 | fs_res_t linuxfs_readdir(void * rddir_p, char * fn) 264 | { 265 | errno = 0; 266 | DIR ** rd = rddir_p; 267 | if(*rd == NULL) return FS_RES_INV_PARAM; 268 | 269 | struct dirent *dirp; 270 | 271 | do { 272 | dirp = readdir(*rd); 273 | if(dirp == NULL){ 274 | fn[0] = '\0'; 275 | break; 276 | } 277 | } while(dirp->d_name[0] == '.'); /*Ignore "." and ".."*/ 278 | 279 | /*Save the filename*/ 280 | if(dirp != NULL) { 281 | if(dirp->d_type == DT_DIR) sprintf(fn, "/%s", dirp->d_name); 282 | else sprintf(fn, "%s", dirp->d_name); 283 | } 284 | 285 | return linuxfs_res_trans(errno); 286 | } 287 | 288 | /** 289 | * Close the directory reading 290 | * @param rddir_p pointer to an initialized 'DIR' variable 291 | * @return FS_RES_OK or any error from fs_res_t enum 292 | */ 293 | fs_res_t linuxfs_readdir_close(void * rddir_p) 294 | { 295 | DIR ** rd = rddir_p; 296 | if(*rd == NULL) return FS_RES_INV_PARAM; 297 | 298 | errno = 0; 299 | closedir(*rd); 300 | return FS_RES_OK; 301 | } 302 | 303 | /********************** 304 | * STATIC FUNCTIONS 305 | **********************/ 306 | 307 | /** 308 | * Translate the return codes to fs_res_t 309 | * @param linuxfs_res the original fat_32 result 310 | * @return the converted, fs_res_t return code 311 | */ 312 | 313 | static fs_res_t linuxfs_res_trans(int linuxfs_res) 314 | { 315 | if(linuxfs_res == 0) return FS_RES_OK; 316 | return FS_RES_UNKNOWN; 317 | } 318 | 319 | #endif 320 | -------------------------------------------------------------------------------- /fs/linuxfs/linuxfs.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file linuxfs.c 3 | * Functions to give an API to the standard 4 | * file operation functions to be compatible 5 | */ 6 | 7 | 8 | #ifndef LINUXFS_H 9 | #define LINUXFS_H 10 | 11 | #ifdef __cplusplus 12 | extern "C" { 13 | #endif 14 | 15 | 16 | /********************* 17 | * INCLUDES 18 | *********************/ 19 | #include "../../../misc_conf.h" 20 | #if USE_LINUXFS != 0 21 | 22 | #include "../fsint.h" 23 | 24 | /********************* 25 | * DEFINES 26 | *********************/ 27 | 28 | /********************** 29 | * TYPEDEFS 30 | **********************/ 31 | 32 | /********************** 33 | * GLOBAL PROTOTYPES 34 | **********************/ 35 | 36 | /** 37 | * Create a driver for the linuxfs device and initilaize it. 38 | */ 39 | void linuxfs_init(void); 40 | 41 | /** 42 | * Give the state of the linuxfs 43 | * @return true if it is already initialized 44 | */ 45 | bool linuxfs_ready(void); 46 | 47 | /** 48 | * Open a file 49 | * @param file_p pointer to a FIL type variable 50 | * @param path path of the file (e.g. "dir1/dir2/file1.txt") 51 | * @param mode open mode (FS_MODE_RD or FS_MODE_WR or both with | (or connection)) 52 | * @return FS_RES_OK or any error from 'fs_res_t' 53 | */ 54 | fs_res_t linuxfs_open (void * file_p, const char * path, fs_mode_t mode); 55 | 56 | /** 57 | * Close an already opened file 58 | * @param file_p pointer to a FIL type variable 59 | * @return FS_RES_OK or any error from fs_res_t 60 | */ 61 | fs_res_t linuxfs_close (void * file_p); 62 | 63 | /** 64 | * Remove (delete) a file 65 | * @param path the path of the file ("dir1/file1.txt") 66 | * @return FS_RES_OK or any error from 'fs_res_t' 67 | */ 68 | fs_res_t linuxfs_remove(const char * path); 69 | 70 | /** 71 | * Read data from an opened file 72 | * @param file_p pointer to a FIL type variable 73 | * @param buf pointer a buffer to store the read bytes 74 | * @param btr the number of Bytes To Read 75 | * @param br the number of real read bytes (Bytes Read) 76 | * @return FS_RES_OK or any error from 'fs_res_t' 77 | */ 78 | fs_res_t linuxfs_read (void * file_p, void * buf, uint32_t btr, uint32_t * br); 79 | 80 | /** 81 | * Write data to an opened file 82 | * @param file_p pointer to a FIL type variable 83 | * @param buf pointer to buffer where the data to write is located 84 | * @param btw the number of Bytes To Write 85 | * @param bw the number of real written bytes (Bytes Written) 86 | * @return FS_RES_OK or any error from 'fs_res_t' 87 | */ 88 | fs_res_t linuxfs_write (void * file_p, const void * buf, uint32_t btw, uint32_t * bw); 89 | 90 | /** 91 | * Position the read write pointer to given position 92 | * @param file_p pointer to a FIL type variable 93 | * @param pos the new position expressed in bytes index (0: start of file) 94 | * @return FS_RES_OK or any error from 'fs_res_t' 95 | */ 96 | fs_res_t linuxfs_seek (void * file_p, uint32_t pos); 97 | 98 | /** 99 | * Give the position of the read write pointer 100 | * @param file_p pointer to a FIL type variable 101 | * @param pos_p pointer to store the position of the read write pointer 102 | * @return FS_RES_OK or any error from 'fs_res_t' 103 | */ 104 | fs_res_t linuxfs_tell (void * file_p, uint32_t * pos_p); 105 | 106 | /** 107 | * Give the size of a file 108 | * @param file_p pointer to a FIL type variable 109 | * @param size_p pointer to store the size 110 | * @return FS_RES_OK or any error from 'fs_res_t' 111 | */ 112 | fs_res_t linuxfs_size (void * file_p, uint32_t * size_p); 113 | 114 | /** 115 | * Initialize a variable for directory reading 116 | * @param rddir_p pointer to a 'DIR' variable 117 | * @param path path to a directory 118 | * @return FS_RES_OK or any error from fs_res_t enum 119 | */ 120 | fs_res_t linuxfs_readdir_init(void * rddir_p, const char * path); 121 | 122 | /** 123 | * Read the next filename form a directory. 124 | * The name of the directories will begin with '/' 125 | * @param rddir_p pointer to an initialized 'DIR' variable 126 | * @param fn pointer to a buffer to store the filename 127 | * @return FS_RES_OK or any error from fs_res_t enum 128 | */ 129 | fs_res_t linuxfs_readdir(void * rddir_p, char * fn); 130 | 131 | /** 132 | * Close the directory reading 133 | * @param rddir_p pointer to an initialized 'DIR' variable 134 | * @return FS_RES_OK or any error from fs_res_t enum 135 | */ 136 | fs_res_t linuxfs_readdir_close(void * rddir_p); 137 | 138 | /********************** 139 | * MACROS 140 | **********************/ 141 | 142 | #endif 143 | 144 | #ifdef __cplusplus 145 | } /* extern "C" */ 146 | #endif 147 | 148 | 149 | #endif 150 | -------------------------------------------------------------------------------- /fs/ufs/ufs.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file ufs.h 3 | * Implementation of RAM file system which do NOT support directories. 4 | * The API is compatible with the fs_int module. 5 | */ 6 | 7 | #ifndef UFS_H 8 | #define UFS_H 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | 15 | /********************* 16 | * INCLUDES 17 | *********************/ 18 | #include "../../../misc_conf.h" 19 | #if USE_UFS != 0 20 | 21 | #include 22 | #include "../fsint.h" 23 | #include "../../mem/dyn_mem.h" 24 | 25 | /********************* 26 | * DEFINES 27 | *********************/ 28 | 29 | /********************** 30 | * TYPEDEFS 31 | **********************/ 32 | /*Description of a file entry */ 33 | typedef struct 34 | { 35 | char * fn_d; 36 | void * data_d; 37 | uint32_t size; /*Data length in bytes*/ 38 | uint16_t oc; /*Open Count*/ 39 | uint8_t const_data :1; 40 | }ufs_ent_t; 41 | 42 | /*File descriptor, used to handle opening an entry more times simultaneously 43 | Contains unique informations about the specific opening*/ 44 | typedef struct 45 | { 46 | ufs_ent_t* ent; /*Pointer to the entry*/ 47 | uint32_t rwp; /*Read Write Pointer*/ 48 | uint8_t ar :1; /*1: Access for read is enabled */ 49 | uint8_t aw :1; /*1: Access for write is enabled */ 50 | }ufs_file_t; 51 | 52 | /* Read directory descriptor. 53 | * It is used to to iterate through the entries in a directory*/ 54 | typedef struct 55 | { 56 | ufs_ent_t * last_ent; 57 | }ufs_read_dir_t; 58 | 59 | /********************** 60 | * GLOBAL PROTOTYPES 61 | **********************/ 62 | 63 | /** 64 | * Create a driver for ufs and initialize it. 65 | */ 66 | void ufs_init(void); 67 | 68 | /** 69 | * Give the state of the ufs 70 | * @return true if ufs is initialized and can be used else false 71 | */ 72 | bool ufs_ready(void); 73 | 74 | /** 75 | * Open a file in ufs 76 | * @param file_p pointer to a ufs_file_t variable 77 | * @param fn name of the file. There are no directories so e.g. "myfile.txt" 78 | * @param mode element of 'fs_mode_t' enum or its 'OR' connection (e.g. FS_MODE_WR | FS_MODE_RD) 79 | * @return FS_RES_OK: no error, the file is opened 80 | * any error from fs_res_t enum 81 | */ 82 | fs_res_t ufs_open (void * file_p, const char * fn, fs_mode_t mode); 83 | 84 | /** 85 | * Create a file with a constant data 86 | * @param fn name of the file (directories are not supported) 87 | * @param const_p pointer to a constant data 88 | * @param len length of the data pointed by 'const_p' in bytes 89 | * @return FS_RES_OK: no error, the file is read 90 | * any error from fs_res_t enum 91 | */ 92 | fs_res_t ufs_create_const(const char * fn, const void * const_p, uint32_t len); 93 | 94 | /** 95 | * Close an opened file 96 | * @param file_p pointer to an 'ufs_file_t' variable. (opened with ufs_open) 97 | * @return FS_RES_OK: no error, the file is read 98 | * any error from fs_res_t enum 99 | */ 100 | fs_res_t ufs_close (void * file_p); 101 | 102 | /** 103 | * Remove a file. The file can not be opened. 104 | * @param fn '\0' terminated string 105 | * @return FS_RES_OK: no error, the file is removed 106 | * FS_RES_DENIED: the file was opened, remove failed 107 | */ 108 | fs_res_t ufs_remove(const char * fn); 109 | 110 | /** 111 | * Read data from an opened file 112 | * @param file_p pointer to an 'ufs_file_t' variable. (opened with ufs_open ) 113 | * @param buf pointer to a memory block where to store the read data 114 | * @param btr number of Bytes To Read 115 | * @param br the real number of read bytes (Byte Read) 116 | * @return FS_RES_OK: no error, the file is read 117 | * any error from fs_res_t enum 118 | */ 119 | fs_res_t ufs_read (void * file_p, void * buf, uint32_t btr, uint32_t * br); 120 | 121 | /** 122 | * Write data to an opened file 123 | * @param file_p pointer to an 'ufs_file_t' variable. (opened with ufs_open) 124 | * @param buf pointer to a memory block which content will be written 125 | * @param btw the number Bytes To Write 126 | * @param bw The real number of written bytes (Byte Written) 127 | * @return FS_RES_OK: no error, the file is read 128 | * any error from fs_res_t enum 129 | */ 130 | fs_res_t ufs_write (void * file_p, const void * buf, uint32_t btw, uint32_t * bw); 131 | 132 | /** 133 | * Set the read write pointer. Also expand the file size if necessary. 134 | * @param file_p pointer to an 'ufs_file_t' variable. (opened with ufs_open ) 135 | * @param pos the new position of read write pointer 136 | * @return FS_RES_OK: no error, the file is read 137 | * any error from fs_res_t enum 138 | */ 139 | fs_res_t ufs_seek (void * file_p, uint32_t pos); 140 | 141 | /** 142 | * Give the position of the read write pointer 143 | * @param file_p pointer to an 'ufs_file_t' variable. (opened with ufs_open ) 144 | * @param pos_p pointer to to store the result 145 | * @return FS_RES_OK: no error, the file is read 146 | * any error from fs_res_t enum 147 | */ 148 | fs_res_t ufs_tell (void * file_p, uint32_t * pos_p); 149 | 150 | /** 151 | * Truncate the file size to the current position of the read write pointer 152 | * @param file_p pointer to an 'ufs_file_t' variable. (opened with ufs_open ) 153 | * @return FS_RES_OK: no error, the file is read 154 | * any error from fs_res_t enum 155 | */ 156 | fs_res_t ufs_trunc (void * file_p); 157 | 158 | /** 159 | * Give the size of the file in bytes 160 | * @param file_p file_p pointer to an 'ufs_file_t' variable. (opened with ufs_open ) 161 | * @param size_p pointer to store the size 162 | * @return FS_RES_OK: no error, the file is read 163 | * any error from fs_res_t enum 164 | */ 165 | fs_res_t ufs_size (void * file_p, uint32_t * size_p); 166 | 167 | /** 168 | * Initialize a ufs_read_dir_t variable to directory reading 169 | * @param rddir_p pointer to a 'ufs_read_dir_t' variable 170 | * @param path uFS doesn't support folders so it has to be "" 171 | * @return FS_RES_OK or any error from fs_res_t enum 172 | */ 173 | fs_res_t ufs_readdir_init(void * rddir_p, const char * path); 174 | 175 | /** 176 | * Read the next file name 177 | * @param rddir_p pointer to an initialized 'ufs_read_dir_t' variable 178 | * @param fn pointer to buffer to sore the file name 179 | * @return FS_RES_OK or any error from fs_res_t enum 180 | */ 181 | fs_res_t ufs_readdir(void * rddir_p, char * fn); 182 | 183 | /** 184 | * Close the directory reading 185 | * @param rddir_p pointer to an initialized 'ufs_read_dir_t' variable 186 | * @return FS_RES_OK or any error from fs_res_t enum 187 | */ 188 | fs_res_t ufs_readdir_close(void * rddir_p); 189 | 190 | /** 191 | * Give the size of a drive 192 | * @param total_p pointer to store the total size [kB] 193 | * @param free_p pointer to store the free site [kB] 194 | * @return FS_RES_OK or any error from 'fs_res_t' 195 | */ 196 | fs_res_t ufs_free (uint32_t * total_p, uint32_t * free_p); 197 | 198 | /********************** 199 | * MACROS 200 | **********************/ 201 | 202 | #endif 203 | 204 | #ifdef __cplusplus 205 | } /* extern "C" */ 206 | #endif 207 | 208 | 209 | #endif 210 | -------------------------------------------------------------------------------- /gfx/anim.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file anim.c 3 | * 4 | */ 5 | 6 | /********************* 7 | * INCLUDES 8 | *********************/ 9 | #include "../../misc_conf.h" 10 | #include "../os/ptask.h" 11 | #include "anim.h" 12 | #include 13 | #include 14 | 15 | #if USE_ANIM != 0 16 | #include "../math/math_base.h" 17 | #include "hal/systick/systick.h" 18 | 19 | /********************* 20 | * DEFINES 21 | *********************/ 22 | #define ANIM_PATH_LENGTH 129 /*Elements in a path array*/ 23 | #define ANIM_PATH_START 64 /*In path array a value which corresponds to the start position*/ 24 | #define ANIM_PATH_END 192 /* ... to the end position. Not required, just for clearance.*/ 25 | #define ANIM_PATH_NORM_SHIFT 7 /*ANIM_PATH_START - ANIM_PATH_END. Must be 2^N. The exponent goes here. */ 26 | 27 | /********************** 28 | * TYPEDEFS 29 | **********************/ 30 | 31 | /********************** 32 | * STATIC PROTOTYPES 33 | **********************/ 34 | static void anim_task (void * param); 35 | static bool anim_ready_handler(anim_t * a); 36 | 37 | /********************** 38 | * STATIC VARIABLES 39 | **********************/ 40 | static ll_dsc_t anim_ll; 41 | static uint32_t last_task_run; 42 | static bool anim_del_global_flag = false; 43 | 44 | static anim_path_t anim_path_lin[] = 45 | {64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 46 | 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 47 | 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 48 | 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192}; 49 | 50 | static anim_path_t anim_path_step[] = 51 | {64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 52 | 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 53 | 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 54 | 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 192,}; 55 | 56 | /********************** 57 | * MACROS 58 | **********************/ 59 | 60 | /********************** 61 | * GLOBAL FUNCTIONS 62 | **********************/ 63 | 64 | /** 65 | * Init. the animation module 66 | */ 67 | void anim_init(void) 68 | { 69 | ll_init(&anim_ll, sizeof(anim_t)); 70 | last_task_run = systick_get(); 71 | ptask_create(anim_task, ANIM_REFR_PERIOD, PTASK_PRIO_MID, NULL); 72 | } 73 | 74 | /** 75 | * Create an animation 76 | * @param anim_p an initialized 'anim_t' variable. Not required after call. 77 | */ 78 | void anim_create(anim_t * anim_p) 79 | { 80 | /* Do not let two animations for the same 'var' with the same 'fp'*/ 81 | if(anim_p->fp != NULL) anim_del(anim_p->var, anim_p->fp); /*fp == NULL would delete all animations of var*/ 82 | 83 | /*Add the new animation to the animation linked list*/ 84 | anim_t * new_anim = ll_ins_head(&anim_ll); 85 | dm_assert(new_anim); 86 | 87 | /*Initialize the animation descriptor*/ 88 | anim_p->playback_now = 0; 89 | memcpy(new_anim, anim_p, sizeof(anim_t)); 90 | 91 | /*Set the start value*/ 92 | if(new_anim->fp != NULL) new_anim->fp(new_anim->var, new_anim->start); 93 | } 94 | 95 | /** 96 | * Delete an animation for a variable with a given animatior function 97 | * @param var pointer to variable 98 | * @param fp a function pointer which is animating 'var', 99 | * or NULL to delete all animations of 'var' 100 | * @return true: at least 1 animation is deleted, false: no animation is deleted 101 | */ 102 | bool anim_del(void * var, anim_fp_t fp) 103 | { 104 | bool del = false; 105 | anim_t * a; 106 | anim_t * a_next; 107 | a = ll_get_head(&anim_ll); 108 | while(a != NULL) { 109 | /*'a' might be deleted, so get the next object while 'a' is valid*/ 110 | a_next = ll_get_next(&anim_ll, a); 111 | 112 | if(a->var == var && (a->fp == fp || fp == NULL)) { 113 | ll_rem(&anim_ll, a); 114 | dm_free(a); 115 | del = true; 116 | anim_del_global_flag = true; 117 | } 118 | 119 | a = a_next; 120 | } 121 | 122 | return del; 123 | } 124 | 125 | /** 126 | * Calculate the time of an animation with a given speed and the start and end values 127 | * @param speed speed of animation in unit/sec 128 | * @param start start value of the animation 129 | * @param end end value of the animation 130 | * @return the required time [ms] for the animation with the given parameters 131 | */ 132 | uint16_t anim_speed_to_time(uint16_t speed, int32_t start, int32_t end) 133 | { 134 | int32_t d = MATH_ABS((int32_t) start - end); 135 | uint16_t time = (int32_t)((int32_t)(d * 1000) / speed); 136 | 137 | if(time == 0) { 138 | time++; 139 | } 140 | 141 | return time; 142 | } 143 | 144 | /** 145 | * Get a predefine animation path 146 | * @param name name of the path from 'anim_path_name_t' 147 | * @return pointer to the path array 148 | */ 149 | anim_path_t * anim_get_path(anim_path_name_t name) 150 | { 151 | switch (name) { 152 | case ANIM_PATH_LIN: 153 | return anim_path_lin; 154 | break; 155 | case ANIM_PATH_STEP: 156 | return anim_path_step; 157 | break; 158 | default: 159 | return NULL; 160 | break; 161 | } 162 | } 163 | /********************** 164 | * STATIC FUNCTIONS 165 | **********************/ 166 | 167 | /** 168 | * Periodically handle the animations. 169 | * @param param unused 170 | */ 171 | static void anim_task (void * param) 172 | { 173 | volatile uint32_t elaps; 174 | elaps = systick_elaps(last_task_run); 175 | 176 | 177 | anim_t * a; 178 | anim_t * a_next; 179 | a = ll_get_head(&anim_ll); 180 | while(a != NULL) { 181 | /*'a' might be deleted, so get the next object while 'a' is valid*/ 182 | a_next = ll_get_next(&anim_ll, a); 183 | 184 | a->act_time += elaps; 185 | if(a->act_time >= 0) { 186 | if(a->act_time > a->time) a->act_time = a->time; 187 | 188 | /* Get the index of the path array based on the elapsed time*/ 189 | uint8_t path_i; 190 | if(a->time == a->act_time) { 191 | path_i = ANIM_PATH_LENGTH - 1; /*Use the last value id the time fully elapsed*/ 192 | } else { 193 | path_i = a->act_time * (ANIM_PATH_LENGTH - 1) / a->time; 194 | } 195 | /* Get the new value which will be proportional to the current element of 'path_p' 196 | * and the 'start' and 'end' values*/ 197 | int32_t new_val; 198 | new_val = (int32_t)(a->path[path_i] - ANIM_PATH_START) * (a->end - a->start); 199 | new_val = new_val >> ANIM_PATH_NORM_SHIFT; 200 | new_val += a->start; 201 | 202 | if(a->fp != NULL) a->fp(a->var, new_val); /*Apply the calculated value*/ 203 | 204 | /*If the time is elapsed the animation is ready*/ 205 | if(a->act_time >= a->time) { 206 | bool invalid; 207 | invalid = anim_ready_handler(a); 208 | if(invalid != false) { 209 | a_next = ll_get_head(&anim_ll); /*a_next might be invalid if animation delete occurred*/ 210 | } 211 | } 212 | } 213 | 214 | a = a_next; 215 | } 216 | 217 | last_task_run = systick_get(); 218 | } 219 | 220 | /** 221 | * Called when an animation is ready to do the necessary thinks 222 | * e.g. repeat, play back, delete etc. 223 | * @param a pointer to an animation descriptor 224 | * @return true: animation delete occurred 225 | * */ 226 | static bool anim_ready_handler(anim_t * a) 227 | { 228 | bool invalid = false; 229 | 230 | /*Delete the animation if 231 | * - no repeat and no play back (simple one shot animation) 232 | * - no repeat, play back is enabled and play back is ready */ 233 | if((a->repeat == 0 && a->playback == 0) || 234 | (a->repeat == 0 && a->playback == 1 && a->playback_now == 1)) { 235 | void (*cb) (void *) = a->end_cb; 236 | void * p = a->var; 237 | ll_rem(&anim_ll, a); 238 | dm_free(a); 239 | 240 | /*Call the callback function at the end*/ 241 | /* Check if an animation is deleted in the cb function 242 | * if yes then the caller function has to know this*/ 243 | anim_del_global_flag = false; 244 | if(cb != NULL) cb(p); 245 | invalid = anim_del_global_flag; 246 | } 247 | /*If the animation is not deleted then restart it*/ 248 | else { 249 | a->act_time = - a->repeat_pause; /*Restart the animation*/ 250 | /*Swap the start and end values in play back mode*/ 251 | if(a->playback != 0) { 252 | /*If now turning back use the 'playback_pause*/ 253 | if(a->playback_now == 0) a->act_time = - a->playback_pause; 254 | 255 | /*Toggle the play back state*/ 256 | a->playback_now = a->playback_now == 0 ? 1: 0; 257 | /*Swap the start and end values*/ 258 | int32_t tmp; 259 | tmp = a->start; 260 | a->start = a->end; 261 | a->end = tmp; 262 | } 263 | } 264 | 265 | return invalid; 266 | } 267 | 268 | /*For compatibility add dummy functions*/ 269 | #else 270 | 271 | #if USE_PTASK != 0 272 | static void anim_dummy_handler(void * anim_dm); 273 | #endif 274 | 275 | /** 276 | * Create an animation. Immediately set to end value 277 | * @param anim_p an initialized 'anim_t' variable. Not required after call. 278 | */ 279 | void anim_create(anim_t * anim_p) 280 | { 281 | 282 | /*If no delay simply set the end value end call the callback */ 283 | if(anim_p->act_time == 0) { 284 | if(anim_p->fp != NULL) anim_p->fp(anim_p->var, anim_p->end); 285 | if(anim_p->end_cb != NULL) anim_p->end_cb(anim_p->var); 286 | } 287 | /*With delay set the start value and set a one shot ptask to set end value and call the callback*/ 288 | else { 289 | #if USE_DYN_MEM != 0 && USE_PTASK != 0 290 | if(anim_p->fp != NULL) anim_p->fp(anim_p->var, anim_p->start); 291 | void * anim_dm = dm_alloc(sizeof(anim_t)); 292 | memcpy(anim_dm, anim_p, sizeof(anim_t)); 293 | ptask_t * ptask = ptask_create(anim_dummy_handler, -anim_p->act_time, PTASK_PRIO_LOW, anim_dm); 294 | ptask_once(ptask); 295 | #else 296 | if(anim_p->fp != NULL) anim_p->fp(anim_p->var, anim_p->end); 297 | if(anim_p->end_cb != NULL) anim_p->end_cb(anim_p->var); 298 | #endif 299 | } 300 | } 301 | 302 | /** 303 | * Delete an animation for a variable with a given animatior function (Now do nothing) 304 | * @param var pointer to variable 305 | * @param fp a function pointer which is animating 'var', 306 | * or NULL to ignore it and delete all animation with 'var 307 | * @return true: at least 1 animation is deleted, false: no animation is deleted 308 | */ 309 | bool anim_del(void * var, anim_fp_t fp) 310 | { 311 | return false; 312 | } 313 | 314 | /** 315 | * Calculate the time of an animation with a given speed and the start and end values (Give dummy value) 316 | * @param speed speed of animation in unit/sec 317 | * @param start start value of the animation 318 | * @param end end value of the animation 319 | * @return the required time [ms] for the animation with the given parameters 320 | */ 321 | uint16_t anim_speed_to_time(uint16_t speed, int32_t start, int32_t end) 322 | { 323 | return 1; 324 | } 325 | 326 | /** 327 | * Get a predefine animation path (Give NULL) 328 | * @param name name of the path from 'anim_path_name_t' 329 | * @return pointer to the path array 330 | */ 331 | anim_path_t * anim_get_path(anim_path_name_t name) 332 | { 333 | return NULL; 334 | } 335 | 336 | #if USE_PTASK != 0 337 | 338 | /** 339 | * A One Shot ptask to handle end callbacks with delay 340 | * @param anim_dm pointer to temporal dynamically allocated animation 341 | */ 342 | static void anim_dummy_handler(void * anim_dm) 343 | { 344 | anim_t * anim = anim_dm; 345 | 346 | if(anim->fp != NULL) anim->fp(anim->var, anim->end); 347 | if(anim->end_cb != NULL) anim->end_cb(anim->var); 348 | 349 | dm_free(anim_dm); 350 | } 351 | #endif 352 | 353 | #endif /*USE_ANIM*/ 354 | 355 | -------------------------------------------------------------------------------- /gfx/anim.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file anim.h 3 | * 4 | */ 5 | 6 | #ifndef ANIM_H 7 | #define ANIM_H 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | 14 | /********************* 15 | * INCLUDES 16 | *********************/ 17 | #include "../../misc_conf.h" 18 | /*For compatibility always include this header*/ 19 | 20 | #include 21 | #include 22 | 23 | /********************* 24 | * DEFINES 25 | *********************/ 26 | 27 | /********************** 28 | * TYPEDEFS 29 | **********************/ 30 | 31 | typedef enum 32 | { 33 | ANIM_PATH_LIN, 34 | ANIM_PATH_STEP, 35 | }anim_path_name_t; 36 | 37 | typedef uint8_t anim_path_t; 38 | 39 | typedef void (*anim_fp_t)(void *, int32_t); 40 | typedef void (*anim_cb_t)(void *); 41 | 42 | typedef struct 43 | { 44 | void * var; /*Variable to animate*/ 45 | anim_fp_t fp; /*Animator function*/ 46 | anim_cb_t end_cb; /*Call it when the animation is ready*/ 47 | anim_path_t * path; /*An array with the steps of animations*/ 48 | int32_t start; /*Start value*/ 49 | int32_t end; /*End value*/ 50 | int16_t time; /*Animation time in ms*/ 51 | int16_t act_time; /*Current time in animation. Set to negative to make delay.*/ 52 | uint16_t playback_pause; /*Wait before play back*/ 53 | uint16_t repeat_pause; /*Wait before repeat*/ 54 | uint8_t playback :1; /*When the animation is ready play it back*/ 55 | uint8_t repeat :1; /*Repeat the animation infinitely*/ 56 | /*Animation system use these - user shouldn't set*/ 57 | uint8_t playback_now :1; /*Play back is in progress*/ 58 | }anim_t; 59 | 60 | /*Example initialization 61 | anim_t a; 62 | a.var = obj; 63 | a.start = lv_obj_get_height(obj); 64 | a.end = new_height; 65 | a.fp = (anim_fp_t)lv_obj_set_height; 66 | a.path = anim_get_path(ANIM_PATH_LIN); 67 | a.end_cb = NULL; 68 | a.act_time = 0; 69 | a.time = 200; 70 | a.playback = 0; 71 | a.playback_pause = 0; 72 | a.repeat = 0; 73 | a.repeat_pause = 0; 74 | */ 75 | /********************** 76 | * GLOBAL PROTOTYPES 77 | **********************/ 78 | 79 | /** 80 | * Init. the animation module 81 | */ 82 | void anim_init(void); 83 | 84 | /** 85 | * Create an animation 86 | * @param anim_p an initialized 'anim_t' variable. Not required after call. 87 | */ 88 | void anim_create(anim_t * anim_p); 89 | 90 | /** 91 | * Delete an animation for a variable with a given animatior function 92 | * @param var pointer to variable 93 | * @param fp a function pointer which is animating 'var', 94 | * or NULL to ignore it and delete all animation with 'var 95 | * @return true: at least 1 animation is deleted, false: no animation is deleted 96 | */ 97 | bool anim_del(void * var, anim_fp_t fp); 98 | 99 | /** 100 | * Calculate the time of an animation with a given speed and the start and end values 101 | * @param speed speed of animation in unit/sec 102 | * @param start start value of the animation 103 | * @param end end value of the animation 104 | * @return the required time [ms] for the animation with the given parameters 105 | */ 106 | uint16_t anim_speed_to_time(uint16_t speed, int32_t start, int32_t end); 107 | 108 | /** 109 | * Get a predefine animation path 110 | * @param name name of the path from 'anim_path_name_t' 111 | * @return pointer to the path array 112 | */ 113 | anim_path_t * anim_get_path(anim_path_name_t name); 114 | 115 | /********************** 116 | * MACROS 117 | **********************/ 118 | 119 | #ifdef __cplusplus 120 | } /* extern "C" */ 121 | #endif 122 | 123 | #endif 124 | -------------------------------------------------------------------------------- /gfx/area.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 2d.c 3 | * 4 | */ 5 | 6 | /********************* 7 | * INCLUDES 8 | *********************/ 9 | #include "../../misc_conf.h" 10 | #if USE_AREA != 0 11 | 12 | #include "area.h" 13 | #include "../math/math_base.h" 14 | 15 | /********************* 16 | * DEFINES 17 | *********************/ 18 | 19 | /********************** 20 | * TYPEDEFS 21 | **********************/ 22 | 23 | /********************** 24 | * STATIC PROTOTYPES 25 | **********************/ 26 | 27 | /********************** 28 | * STATIC VARIABLES 29 | **********************/ 30 | 31 | /********************** 32 | * MACROS 33 | **********************/ 34 | 35 | /********************** 36 | * GLOBAL FUNCTIONS 37 | **********************/ 38 | 39 | /** 40 | * Initialize an area 41 | * @param area_p pointer to an area 42 | * @param x1 left coordinate of the area 43 | * @param y1 top coordinate of the area 44 | * @param x2 right coordinate of the area 45 | * @param y2 bottom coordinate of the area 46 | */ 47 | void area_set(area_t * area_p, cord_t x1, cord_t y1, cord_t x2, cord_t y2) 48 | { 49 | area_p->x1 = x1; 50 | area_p->y1 = y1; 51 | area_p->x2 = x2; 52 | area_p->y2 = y2; 53 | } 54 | 55 | /** 56 | * Set the width of an area 57 | * @param area_p pointer to an area 58 | * @param w the new width of the area (w == 1 makes x1 == x2) 59 | */ 60 | void area_set_width(area_t * area_p, cord_t w) 61 | { 62 | area_p->x2 = area_p->x1 + w - 1; 63 | } 64 | 65 | /** 66 | * Set the height of an area 67 | * @param area_p pointer to an area 68 | * @param h the new height of the area (h == 1 makes y1 == y2) 69 | */ 70 | void area_set_height(area_t * area_p, cord_t h) 71 | { 72 | area_p->y2 = area_p->y1 + h - 1; 73 | } 74 | 75 | /** 76 | * Set the position of an area (width and height will be kept) 77 | * @param area_p pointer to an area 78 | * @param x the new x coordinate of the area 79 | * @param y the new y coordinate of the area 80 | */ 81 | void area_set_pos(area_t * area_p, cord_t x, cord_t y) 82 | { 83 | cord_t w = area_get_width(area_p); 84 | cord_t h = area_get_height(area_p); 85 | area_p->x1 = x; 86 | area_p->y1 = y; 87 | area_set_width(area_p, w); 88 | area_set_height(area_p, h); 89 | } 90 | 91 | /** 92 | * Return with area of an area (x * y) 93 | * @param area_p pointer to an area 94 | * @return size of area 95 | */ 96 | uint32_t area_get_size(const area_t * area_p) 97 | { 98 | uint32_t size; 99 | 100 | size = (uint32_t)(area_p->x2 - area_p->x1 + 1) * 101 | (area_p->y2 - area_p->y1 + 1); 102 | 103 | return size; 104 | } 105 | 106 | /** 107 | * Get the common parts of two areas 108 | * @param res_p pointer to an area, the result will be stored her 109 | * @param a1_p pointer to the first area 110 | * @param a2_p pointer to the second area 111 | * @return false: the two area has NO common parts, res_p is invalid 112 | */ 113 | bool area_union(area_t * res_p, const area_t * a1_p, const area_t * a2_p) 114 | { 115 | /* Get the smaller area from 'a1_p' and 'a2_p' */ 116 | res_p->x1 = MATH_MAX(a1_p->x1, a2_p->x1); 117 | res_p->y1 = MATH_MAX(a1_p->y1, a2_p->y1); 118 | res_p->x2 = MATH_MIN(a1_p->x2, a2_p->x2); 119 | res_p->y2 = MATH_MIN(a1_p->y2, a2_p->y2); 120 | 121 | /*If x1 or y1 greater then x2 or y2 then the areas union is empty*/ 122 | bool union_ok = true; 123 | if((res_p->x1 > res_p->x2) || 124 | (res_p->y1 > res_p->y2)) 125 | { 126 | union_ok = false; 127 | } 128 | 129 | return union_ok; 130 | } 131 | /** 132 | * Join two areas into a third which involves the other two 133 | * @param res_p pointer to an area, the result will be stored here 134 | * @param a1_p pointer to the first area 135 | * @param a2_p pointer to the second area 136 | */ 137 | void area_join(area_t * a_res_p, const area_t * a1_p, const area_t * a2_p) 138 | { 139 | a_res_p->x1 = MATH_MIN(a1_p->x1, a2_p->x1); 140 | a_res_p->y1 = MATH_MIN(a1_p->y1, a2_p->y1); 141 | a_res_p->x2 = MATH_MAX(a1_p->x2, a2_p->x2); 142 | a_res_p->y2 = MATH_MAX(a1_p->y2, a2_p->y2); 143 | } 144 | 145 | /** 146 | * Check if a point is on an area 147 | * @param a_p pointer to an area 148 | * @param p_p pointer to a point 149 | * @return false:the point is out of the area 150 | */ 151 | bool area_is_point_on(const area_t * a_p, const point_t * p_p) 152 | { 153 | bool is_on = false; 154 | 155 | if((p_p->x >= a_p->x1 && p_p->x <= a_p->x2) && 156 | ((p_p->y >= a_p->y1 && p_p->y <= a_p->y2))) 157 | { 158 | is_on = true; 159 | } 160 | 161 | return is_on; 162 | } 163 | 164 | /** 165 | * Check if two area has common parts 166 | * @param a1_p pointer to an area. 167 | * @param a2_p pointer to an other area 168 | * @return false: a1_p and a2_p has no common parts 169 | */ 170 | bool area_is_on(const area_t * a1_p, const area_t * a2_p) 171 | { 172 | /*Two area are on each other if... */ 173 | 174 | point_t p; 175 | /*a2 left-top corner is on a1*/ 176 | p.x = a2_p->x1; 177 | p.y = a2_p->y1; 178 | if(area_is_point_on(a1_p, &p)) return true; 179 | 180 | /*a2 right-top corner is on a1*/ 181 | p.x = a2_p->x1; 182 | p.y = a2_p->y1; 183 | if(area_is_point_on(a1_p, &p)) return true; 184 | 185 | /*a2 left-bottom corner is on a1*/ 186 | p.x = a2_p->x1; 187 | p.y = a2_p->y2; 188 | if(area_is_point_on(a1_p, &p)) return true; 189 | 190 | /*a2 right-bottom corner is on a1*/ 191 | p.x = a2_p->x2; 192 | p.y = a2_p->y2; 193 | if(area_is_point_on(a1_p, &p)) return true; 194 | 195 | /*a2 is horizontally bigger then a1 and covers it*/ 196 | if((a2_p->x1 <= a1_p->x1 && a2_p->x2 >= a1_p->x2) && /*a2 hor. cover a1?*/ 197 | ((a2_p->y1 <= a1_p->y1 && a2_p->y1 >= a1_p->y2) || /*upper edge is on a1?*/ 198 | (a2_p->y2 <= a1_p->y1 && a2_p->y2 >= a1_p->y2) ||/* or lower edge is on a1?*/ 199 | (a2_p->y1 <= a1_p->y1 && a2_p->y2 >= a1_p->y2))) /*or a2 vert bigger then a1*/ 200 | return true; 201 | 202 | /*a2 is vertically bigger then a1 and covers it*/ 203 | if((a2_p->y1 <= a1_p->y1 && a2_p->y2 >= a1_p->y2) && /*a2 vert. cover a1?*/ 204 | ((a2_p->x1 <= a1_p->x1 && a2_p->x1 >= a1_p->x2) || /*left edge is on a1?*/ 205 | (a2_p->x2 <= a1_p->x1 && a2_p->x2 >= a1_p->x2) ||/* or right edge is on a1?*/ 206 | (a2_p->x1 <= a1_p->x1 && a2_p->x2 >= a1_p->x2))) /*or a2 hor. bigger then a1*/ 207 | return true; 208 | 209 | /*Else no cover*/ 210 | return false; 211 | } 212 | 213 | /** 214 | * Check if an area is fully on an other 215 | * @param ain_p pointer to an area which could be on aholder_p 216 | * @param aholder pointer to an area which could involve ain_p 217 | * @return 218 | */ 219 | bool area_is_in(const area_t * ain_p, const area_t * aholder_p) 220 | { 221 | bool is_in = false; 222 | 223 | if(ain_p->x1 >= aholder_p->x1 && 224 | ain_p->y1 >= aholder_p->y1 && 225 | ain_p->x2 <= aholder_p->x2 && 226 | ain_p->y2 <= aholder_p->y2) 227 | { 228 | is_in = true; 229 | } 230 | 231 | return is_in; 232 | } 233 | 234 | /********************** 235 | * STATIC FUNCTIONS 236 | **********************/ 237 | 238 | #endif /*USE_AREA*/ 239 | -------------------------------------------------------------------------------- /gfx/area.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file area.h 3 | * 4 | */ 5 | 6 | #ifndef AREA_H 7 | #define AREA_H 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | 14 | /********************* 15 | * INCLUDES 16 | *********************/ 17 | #include "../../misc_conf.h" 18 | #if USE_AREA != 0 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | /********************* 25 | * DEFINES 26 | *********************/ 27 | #define CORD_MAX (16383) /*To avoid overflow don't let the max [-32,32k] range */ 28 | #define CORD_MIN (-16384) 29 | 30 | /********************** 31 | * TYPEDEFS 32 | **********************/ 33 | typedef int16_t cord_t; 34 | 35 | typedef struct 36 | { 37 | cord_t x; 38 | cord_t y; 39 | }point_t; 40 | 41 | typedef struct 42 | { 43 | cord_t x1; 44 | cord_t y1; 45 | cord_t x2; 46 | cord_t y2; 47 | }area_t; 48 | 49 | /********************** 50 | * GLOBAL PROTOTYPES 51 | **********************/ 52 | 53 | /** 54 | * Initialize an area 55 | * @param area_p pointer to an area 56 | * @param x1 left coordinate of the area 57 | * @param y1 top coordinate of the area 58 | * @param x2 right coordinate of the area 59 | * @param y2 bottom coordinate of the area 60 | */ 61 | void area_set(area_t * area_p, cord_t x1, cord_t y1, cord_t x2, cord_t y2); 62 | 63 | /** 64 | * Copy an area 65 | * @param dest pointer to the destination area 66 | * @param src pointer to the source area 67 | */ 68 | static void inline area_cpy(area_t * dest, const area_t * src) 69 | { 70 | memcpy(dest, src, sizeof(area_t)); 71 | } 72 | 73 | /** 74 | * Get the width of an area 75 | * @param area_p pointer to an area 76 | * @return the width of the area (if x1 == x2 -> width = 1) 77 | */ 78 | static inline cord_t area_get_width(const area_t * area_p) 79 | { 80 | return area_p->x2 - area_p->x1 + 1; 81 | } 82 | 83 | /** 84 | * Get the height of an area 85 | * @param area_p pointer to an area 86 | * @return the height of the area (if y1 == y2 -> height = 1) 87 | */ 88 | static inline cord_t area_get_height(const area_t * area_p) 89 | { 90 | return area_p->y2 - area_p->y1 + 1; 91 | } 92 | 93 | /** 94 | * Set the width of an area 95 | * @param area_p pointer to an area 96 | * @param w the new width of the area (w == 1 makes x1 == x2) 97 | */ 98 | void area_set_width(area_t * area_p, cord_t w); 99 | 100 | /** 101 | * Set the height of an area 102 | * @param area_p pointer to an area 103 | * @param h the new height of the area (h == 1 makes y1 == y2) 104 | */ 105 | void area_set_height(area_t * area_p, cord_t h); 106 | 107 | /** 108 | * Set the position of an area (width and height will be kept) 109 | * @param area_p pointer to an area 110 | * @param x the new x coordinate of the area 111 | * @param y the new y coordinate of the area 112 | */ 113 | void area_set_pos(area_t * area_p, cord_t x, cord_t y); 114 | 115 | /** 116 | * Return with area of an area (x * y) 117 | * @param area_p pointer to an area 118 | * @return size of area 119 | */ 120 | uint32_t area_get_size(const area_t * area_p); 121 | 122 | /** 123 | * Get the common parts of two areas 124 | * @param res_p pointer to an area, the result will be stored her 125 | * @param a1_p pointer to the first area 126 | * @param a2_p pointer to the second area 127 | * @return false: the two area has NO common parts, res_p is invalid 128 | */ 129 | bool area_union(area_t * res_p, const area_t * a1_p, const area_t * a2_p); 130 | 131 | /** 132 | * Join two areas into a third which involves the other two 133 | * @param res_p pointer to an area, the result will be stored here 134 | * @param a1_p pointer to the first area 135 | * @param a2_p pointer to the second area 136 | */ 137 | void area_join(area_t * a_res_p, const area_t * a1_p, const area_t * a2_p); 138 | 139 | /** 140 | * Check if a point is on an area 141 | * @param a_p pointer to an area 142 | * @param p_p pointer to a point 143 | * @return false:the point is out of the area 144 | */ 145 | bool area_is_point_on(const area_t * a_p, const point_t * p_p); 146 | 147 | /** 148 | * Check if two area has common parts 149 | * @param a1_p pointer to an area. 150 | * @param a2_p pointer to an other area 151 | * @return false: a1_p and a2_p has no common parts 152 | */ 153 | bool area_is_on(const area_t * a1_p, const area_t * a2_p); 154 | 155 | /** 156 | * Check if an area is fully on an other 157 | * @param ain_p pointer to an area which could be on aholder_p 158 | * @param aholder pointer to an area which could involve ain_p 159 | * @return 160 | */ 161 | bool area_is_in(const area_t * ain_p, const area_t * aholder_p); 162 | 163 | /********************** 164 | * MACROS 165 | **********************/ 166 | 167 | #endif /*USE_AREA*/ 168 | 169 | #ifdef __cplusplus 170 | } /* extern "C" */ 171 | #endif 172 | 173 | 174 | #endif 175 | -------------------------------------------------------------------------------- /gfx/circ.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file circ.c 3 | * Circle drawing algorithm (with Bresenham) 4 | * Only a 1/8 circle is calculated. Use CIRC_OCT1_X, CIRC_OCT1_Y macros to get 5 | * the other octets. 6 | */ 7 | 8 | /********************* 9 | * INCLUDES 10 | *********************/ 11 | #include "../../misc_conf.h" 12 | #if USE_CIRC != 0 13 | 14 | #include "area.h" 15 | 16 | /********************* 17 | * DEFINES 18 | *********************/ 19 | 20 | /********************** 21 | * TYPEDEFS 22 | **********************/ 23 | 24 | /********************** 25 | * STATIC PROTOTYPES 26 | **********************/ 27 | 28 | /********************** 29 | * STATIC VARIABLES 30 | **********************/ 31 | 32 | /********************** 33 | * MACROS 34 | **********************/ 35 | 36 | /********************** 37 | * GLOBAL FUNCTIONS 38 | **********************/ 39 | 40 | /** 41 | * Initialize the circle drawing 42 | * @param c pointer to a point. The coordinates will be calculated here 43 | * @param tmp point to a variable. It will store temporary data 44 | * @param radius radius of the circle 45 | */ 46 | void circ_init(point_t * c, cord_t * tmp, cord_t radius) 47 | { 48 | c->x = radius; 49 | c->y = 0; 50 | *tmp = 1 - radius; 51 | } 52 | 53 | /** 54 | * Test the circle drawing is ready or not 55 | * @param c same as in circ_init 56 | * @return true if the circle is not ready yet 57 | */ 58 | bool circ_cont(point_t * c) 59 | { 60 | return c->y <= c->x ? true : false; 61 | } 62 | 63 | /** 64 | * Get the next point from the circle 65 | * @param c same as in circ_init. The next point stored here. 66 | * @param tmp same as in circ_init. 67 | */ 68 | void circ_next(point_t * c, cord_t * tmp) 69 | { 70 | c->y++; 71 | 72 | if (*tmp <= 0) { 73 | (*tmp) += 2 * c->y + 1; // Change in decision criterion for y -> y+1 74 | } else { 75 | c->x--; 76 | (*tmp) += 2 * (c->y - c->x) + 1; // Change for y -> y+1, x -> x-1 77 | } 78 | } 79 | 80 | /********************** 81 | * STATIC FUNCTIONS 82 | **********************/ 83 | #endif /*USE_CIRC*/ 84 | 85 | -------------------------------------------------------------------------------- /gfx/circ.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file circ.h 3 | * 4 | */ 5 | 6 | #ifndef CIRC_H 7 | #define CIRC_H 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | 14 | /********************* 15 | * INCLUDES 16 | *********************/ 17 | #include "../../misc_conf.h" 18 | #if USE_CIRC != 0 19 | 20 | #include 21 | #include 22 | 23 | /********************* 24 | * DEFINES 25 | *********************/ 26 | #define CIRC_OCT1_X(p) (p.x) 27 | #define CIRC_OCT1_Y(p) (p.y) 28 | #define CIRC_OCT2_X(p) (p.y) 29 | #define CIRC_OCT2_Y(p) (p.x) 30 | #define CIRC_OCT3_X(p) (-p.y) 31 | #define CIRC_OCT3_Y(p) (p.x) 32 | #define CIRC_OCT4_X(p) (-p.x) 33 | #define CIRC_OCT4_Y(p) (p.y) 34 | #define CIRC_OCT5_X(p) (-p.x) 35 | #define CIRC_OCT5_Y(p) (-p.y) 36 | #define CIRC_OCT6_X(p) (-p.y) 37 | #define CIRC_OCT6_Y(p) (-p.x) 38 | #define CIRC_OCT7_X(p) (p.y) 39 | #define CIRC_OCT7_Y(p) (-p.x) 40 | #define CIRC_OCT8_X(p) (p.x) 41 | #define CIRC_OCT8_Y(p) (-p.y) 42 | 43 | /********************** 44 | * TYPEDEFS 45 | **********************/ 46 | 47 | /********************** 48 | * GLOBAL PROTOTYPES 49 | **********************/ 50 | 51 | /** 52 | * Initialize the circle drawing 53 | * @param c pointer to a point. The coordinates will be calculated here 54 | * @param tmp point to a variable. It will store temporary data 55 | * @param radius radius of the circle 56 | */ 57 | void circ_init(point_t * c, cord_t * tmp, cord_t radius); 58 | 59 | /** 60 | * Test the circle drawing is ready or not 61 | * @param c same as in circ_init 62 | * @return true if the circle is not ready yet 63 | */ 64 | bool circ_cont(point_t * c); 65 | 66 | /** 67 | * Get the next point from the circle 68 | * @param c same as in circ_init. The next point stored here. 69 | * @param tmp same as in circ_init. 70 | */ 71 | void circ_next(point_t * c, cord_t * tmp); 72 | 73 | /********************** 74 | * MACROS 75 | **********************/ 76 | 77 | #endif /*USE_CIRC*/ 78 | 79 | #ifdef __cplusplus 80 | } /* extern "C" */ 81 | #endif 82 | 83 | 84 | #endif 85 | -------------------------------------------------------------------------------- /gfx/color.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file color.h 3 | * 4 | */ 5 | 6 | #ifndef COLOR_H 7 | #define COLOR_H 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | /********************* 14 | * INCLUDES 15 | *********************/ 16 | #include "../../misc_conf.h" 17 | #if USE_COLOR != 0 18 | 19 | #include 20 | 21 | /********************* 22 | * DEFINES 23 | *********************/ 24 | #define COLOR_BLACK COLOR_MAKE(0x00,0x00,0x00) 25 | #define COLOR_WHITE COLOR_MAKE(0xFF,0xFF,0xFF) 26 | #define COLOR_RED COLOR_MAKE(0xFF,0x00,0x00) 27 | #define COLOR_LIME COLOR_MAKE(0x00,0xFF,0x00) 28 | #define COLOR_BLUE COLOR_MAKE(0x00,0x00,0xFF) 29 | #define COLOR_YELLOW COLOR_MAKE(0xFF,0xFF,0x00) 30 | #define COLOR_CYAN COLOR_MAKE(0x00,0xFF,0xFF) 31 | #define COLOR_AQUA COLOR_CYAN 32 | #define COLOR_MAGENTA COLOR_MAKE(0xFF,0x00,0xFF) 33 | #define COLOR_SILVER COLOR_MAKE(0xC0,0xC0,0xC0) 34 | #define COLOR_GRAY COLOR_MAKE(0x80,0x80,0x80) 35 | #define COLOR_MARRON COLOR_MAKE(0x80,0x00,0x00) 36 | #define COLOR_OLIVE COLOR_MAKE(0x80,0x80,0x00) 37 | #define COLOR_GREEN COLOR_MAKE(0x00,0x80,0x00) 38 | #define COLOR_PURPLE COLOR_MAKE(0x80,0x00,0x80) 39 | #define COLOR_TEAL COLOR_MAKE(0x00,0x80,0x80) 40 | #define COLOR_NAVY COLOR_MAKE(0x00,0x00,0x80) 41 | #define COLOR_ORANGE COLOR_MAKE(0xFF,0xA5,0x00) 42 | 43 | #define OPA_TRANSP 0 44 | #define OPA_0 0 45 | #define OPA_10 25 46 | #define OPA_20 51 47 | #define OPA_30 76 48 | #define OPA_40 102 49 | #define OPA_50 127 50 | #define OPA_60 153 51 | #define OPA_70 178 52 | #define OPA_80 204 53 | #define OPA_90 229 54 | #define OPA_100 255 55 | #define OPA_COVER 255 56 | 57 | 58 | /********************** 59 | * TYPEDEFS 60 | **********************/ 61 | 62 | typedef union 63 | { 64 | uint8_t blue :1; 65 | uint8_t green :1; 66 | uint8_t red :1; 67 | uint8_t full :1; 68 | }color1_t; 69 | 70 | typedef union 71 | { 72 | struct 73 | { 74 | uint8_t blue :2; 75 | uint8_t green :3; 76 | uint8_t red :3; 77 | }; 78 | uint8_t full; 79 | }color8_t; 80 | 81 | typedef union 82 | { 83 | struct 84 | { 85 | uint16_t blue :5; 86 | uint16_t green :6; 87 | uint16_t red :5; 88 | }; 89 | uint16_t full; 90 | }color16_t; 91 | 92 | typedef union 93 | { 94 | struct 95 | { 96 | uint8_t blue; 97 | uint8_t green; 98 | uint8_t red; 99 | }; 100 | uint32_t full; 101 | }color24_t; 102 | 103 | #if COLOR_DEPTH == 1 104 | typedef uint8_t color_int_t; 105 | typedef color1_t color_t; 106 | #elif COLOR_DEPTH == 8 107 | typedef uint8_t color_int_t; 108 | typedef color8_t color_t; 109 | #elif COLOR_DEPTH == 16 110 | typedef uint16_t color_int_t; 111 | typedef color16_t color_t; 112 | #elif COLOR_DEPTH == 24 113 | typedef uint32_t color_int_t; 114 | typedef color24_t color_t; 115 | #else 116 | #error "Invalid COLOR_DEPTH in misc_conf.h! Set it to 1, 8, 16 or 24!" 117 | #endif 118 | 119 | typedef uint8_t opa_t; 120 | 121 | /********************** 122 | * GLOBAL PROTOTYPES 123 | **********************/ 124 | 125 | /*In color conversations: 126 | * - When converting to bigger color type the LSB weight of 1 LSB is calculated 127 | * E.g. 16 bit Red has 5 bits 128 | * 8 bit Red has 2 bits 129 | * ---------------------- 130 | * 8 bit red LSB = (2^5 - 1) / (2^2 - 1) = 31 / 3 = 10 131 | * 132 | * - When calculating to smaller color type simply shift out the LSBs 133 | * E.g. 8 bit Red has 2 bits 134 | * 16 bit Red has 5 bits 135 | * ---------------------- 136 | * Shift right with 5 - 3 = 2 137 | */ 138 | 139 | static inline uint8_t color_to1(color_t color) 140 | { 141 | #if COLOR_DEPTH == 1 142 | return color.full; 143 | #elif COLOR_DEPTH == 8 144 | if((color.red & 0b100) || 145 | (color.green & 0b100) || 146 | (color.blue & 0b10)) { 147 | return 1; 148 | } else { 149 | return 0; 150 | } 151 | #elif COLOR_DEPTH == 16 152 | if((color.red & 0b10000) || 153 | (color.green & 0b100000) || 154 | (color.blue & 0b10000)) { 155 | return 1; 156 | } else { 157 | return 0; 158 | } 159 | #elif COLOR_DEPTH == 24 160 | if((color.red & 0x80) || 161 | (color.green & 0x80) || 162 | (color.blue & 0x80)) { 163 | return 1; 164 | } else { 165 | return 0; 166 | } 167 | #endif 168 | } 169 | 170 | static inline uint8_t color_to8(color_t color) 171 | { 172 | #if COLOR_DEPTH == 1 173 | if(color.full == 0) return 0; 174 | else return 0xFF; 175 | #elif COLOR_DEPTH == 8 176 | return color.full; 177 | #elif COLOR_DEPTH == 16 178 | color8_t ret; 179 | ret.red = color.red >> 2; /* 5 - 3 = 2*/ 180 | ret.green = color.green >> 3; /* 6 - 3 = 3*/ 181 | ret.blue = color.blue >> 3; /* 5 - 2 = 3*/ 182 | return ret.full; 183 | #elif COLOR_DEPTH == 24 184 | color8_t ret; 185 | ret.red = color.red >> 5; /* 8 - 3 = 5*/ 186 | ret.green = color.green >> 5; /* 8 - 3 = 5*/ 187 | ret.blue = color.blue >> 6; /* 8 - 2 = 6*/ 188 | return ret.full; 189 | #endif 190 | } 191 | 192 | static inline uint16_t color_to16(color_t color) 193 | { 194 | #if COLOR_DEPTH == 1 195 | if(color.full == 0) return 0; 196 | else return 0xFFFF; 197 | #elif COLOR_DEPTH == 8 198 | color16_t ret; 199 | ret.red = color.red * 4; /*(2^5 - 1)/(2^3 - 1) = 31/7 = 4*/ 200 | ret.green = color.green * 9; /*(2^6 - 1)/(2^3 - 1) = 63/7 = 9*/ 201 | ret.blue = color.blue * 10; /*(2^5 - 1)/(2^2 - 1) = 31/3 = 10*/ 202 | return ret.full; 203 | #elif COLOR_DEPTH == 16 204 | return color.full; 205 | #elif COLOR_DEPTH == 24 206 | color16_t ret; 207 | ret.red = color.red >> 3; /* 8 - 5 = 3*/ 208 | ret.green = color.green >> 2; /* 8 - 6 = 2*/ 209 | ret.blue = color.blue >> 3; /* 8 - 5 = 3*/ 210 | return ret.full; 211 | #endif 212 | } 213 | 214 | static inline uint32_t color_to24(color_t color) 215 | { 216 | #if COLOR_DEPTH == 1 217 | if(color.full == 0) return 0; 218 | else return 0xFFFFFF; 219 | #elif COLOR_DEPTH == 8 220 | color24_t ret; 221 | ret.red = color.red * 36; /*(2^8 - 1)/(2^3 - 1) = 255/7 = 36*/ 222 | ret.green = color.green * 36; /*(2^8 - 1)/(2^3 - 1) = 255/7 = 36*/ 223 | ret.blue = color.blue * 85; /*(2^8 - 1)/(2^2 - 1) = 255/3 = 85*/ 224 | return ret.full; 225 | #elif COLOR_DEPTH == 16 226 | color24_t ret; 227 | ret.red = color.red * 8; /*(2^8 - 1)/(2^5 - 1) = 255/31 = 8*/ 228 | ret.green = color.green * 4; /*(2^8 - 1)/(2^6 - 1) = 255/63 = 4*/ 229 | ret.blue = color.blue * 8; /*(2^8 - 1)/(2^5 - 1) = 255/31 = 8*/ 230 | return ret.full; 231 | #elif COLOR_DEPTH == 24 232 | return color.full; 233 | #endif 234 | } 235 | 236 | static inline color_t color_mix(color_t c1, color_t c2, uint8_t mix) 237 | { 238 | color_t ret; 239 | ret.red = (uint16_t)((uint16_t) c1.red * mix + (c2.red * (256 - mix))) >> 8; 240 | ret.green = (uint16_t)((uint16_t) c1.green * mix + (c2.green * (256 - mix))) >> 8; 241 | ret.blue = (uint16_t)((uint16_t) c1.blue * mix + (c2.blue * (256 - mix))) >> 8; 242 | return ret; 243 | } 244 | 245 | /** 246 | * Get the brightness of a color 247 | * @param color a color 248 | * @return the brightness [0..255] 249 | */ 250 | static inline uint8_t color_brightness(color_t color) 251 | { 252 | color24_t c24; 253 | c24.full = color_to24(color); 254 | uint16_t bright = 3 * c24.red + c24.blue + 4 * c24.green; 255 | return (uint16_t) bright >> 3; 256 | } 257 | 258 | #if COLOR_DEPTH == 1 259 | #define COLOR_MAKE(r8, g8, b8) ((color_t){b8 >> 7 | g8 >> 7 | r8 >> 7}) 260 | #elif COLOR_DEPTH == 8 261 | #define COLOR_MAKE(r8, g8, b8) ((color_t){{b8 >> 6, g8 >> 5, r8 >> 5}}) 262 | #elif COLOR_DEPTH == 16 263 | #define COLOR_MAKE(r8, g8, b8) ((color_t){{b8 >> 3, g8 >> 2, r8 >> 3}}) 264 | #elif COLOR_DEPTH == 24 265 | #define COLOR_MAKE(r8, g8, b8) ((color_t){{b8, g8, r8}}) 266 | #endif 267 | 268 | /********************** 269 | * MACROS 270 | **********************/ 271 | 272 | #endif /*USE_COLOR*/ 273 | 274 | #ifdef __cplusplus 275 | } /* extern "C" */ 276 | #endif 277 | 278 | #endif 279 | -------------------------------------------------------------------------------- /gfx/font.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file font.c 3 | * 4 | */ 5 | 6 | /********************* 7 | * INCLUDES 8 | *********************/ 9 | #include "../../misc_conf.h" 10 | #if USE_FONT != 0 11 | 12 | #include 13 | #include "font.h" 14 | #include "fonts/dejavu_8.h" 15 | #include "fonts/dejavu_10.h" 16 | #include "fonts/dejavu_14.h" 17 | #include "fonts/dejavu_20.h" 18 | #include "fonts/dejavu_30.h" 19 | #include "fonts/dejavu_40.h" 20 | #include "fonts/dejavu_60.h" 21 | #include "fonts/dejavu_80.h" 22 | #include "fonts/dejavu_120.h" 23 | #include "fonts/symbol_30.h" 24 | #include "fonts/symbol_60.h" 25 | 26 | /********************* 27 | * DEFINES 28 | *********************/ 29 | 30 | /********************** 31 | * TYPEDEFS 32 | **********************/ 33 | typedef struct 34 | { 35 | }font_map_t; 36 | 37 | /********************** 38 | * STATIC PROTOTYPES 39 | **********************/ 40 | 41 | /********************** 42 | * STATIC VARIABLES 43 | **********************/ 44 | const font_t * (*font_map[FONT_NAME_NUM])(void); 45 | 46 | 47 | /********************** 48 | * GLOBAL PROTOTYPES 49 | **********************/ 50 | 51 | /********************** 52 | * MACROS 53 | **********************/ 54 | 55 | /********************** 56 | * GLOBAL FUNCTIONS 57 | **********************/ 58 | 59 | /** 60 | * Initialize the built-in fonts 61 | */ 62 | void font_init(void) 63 | { 64 | #if USE_FONT_DEJAVU_8 != 0 65 | font_add(FONT_DEJAVU_8, dejavu_8_get_dsc); 66 | #endif 67 | 68 | #if USE_FONT_DEJAVU_10 != 0 69 | font_add(FONT_DEJAVU_10, dejavu_10_get_dsc); 70 | #endif 71 | 72 | #if USE_FONT_DEJAVU_14 != 0 73 | font_add(FONT_DEJAVU_14, dejavu_14_get_dsc); 74 | #endif 75 | 76 | #if USE_FONT_DEJAVU_20 != 0 77 | font_add(FONT_DEJAVU_20, dejavu_20_get_dsc); 78 | #endif 79 | 80 | #if USE_FONT_DEJAVU_30 != 0 81 | font_add(FONT_DEJAVU_30, dejavu_30_get_dsc); 82 | #endif 83 | 84 | #if USE_FONT_DEJAVU_40 != 0 85 | font_add(FONT_DEJAVU_40, dejavu_40_get_dsc); 86 | #endif 87 | 88 | #if USE_FONT_DEJAVU_60 != 0 89 | font_add(FONT_DEJAVU_60, dejavu_60_get_dsc); 90 | #endif 91 | 92 | #if USE_FONT_DEJAVU_80 != 0 93 | font_add(FONT_DEJAVU_80, dejavu_80_get_dsc); 94 | #endif 95 | 96 | #if USE_FONT_DEJAVU_120 != 0 97 | font_add(FONT_DEJAVU_120, dejavu_120_get_dsc); 98 | #endif 99 | 100 | #if USE_FONT_SYMBOL_30 != 0 101 | font_add(FONT_SYMBOL_30, symbol_30_get_dsc); 102 | #endif 103 | 104 | #if USE_FONT_SYMBOL_60 != 0 105 | font_add(FONT_SYMBOL_60, symbol_60_get_dsc); 106 | #endif 107 | } 108 | 109 | /** 110 | * Create a pair from font name and font dsc. get function. After it 'font_get' can be used for this font 111 | * @param name name of the font 112 | * @param dsc_get_fp the font descriptor get function 113 | */ 114 | void font_add(font_name_t name, const font_t * (*dsc_get_fp)(void)) 115 | { 116 | if(name >= FONT_NAME_NUM) return; 117 | 118 | font_map[name] = dsc_get_fp; 119 | } 120 | 121 | 122 | /** 123 | * Get the font from its id 124 | * @param name: name of a font (form 'font_name_t' enum) 125 | * @return pointer to a font descriptor 126 | */ 127 | const font_t * font_get(font_name_t name) 128 | { 129 | 130 | if(name >= FONT_NAME_NUM) return font_map[FONT_DEFAULT](); 131 | 132 | const font_t * font_p = font_map[name](); 133 | 134 | if(font_p == NULL) font_p = font_map[FONT_DEFAULT](); 135 | 136 | return font_p; 137 | } 138 | 139 | /** 140 | * Return with the bitmap of a font. 141 | * @param font_p pointer to a font 142 | * @param letter a letter 143 | * @return pointer to the bitmap of the letter 144 | */ 145 | const uint8_t * font_get_bitmap(const font_t * font_p, uint8_t letter) 146 | { 147 | if(letter < font_p->start_ascii || letter >= font_p->start_ascii + font_p->letter_cnt) return NULL; 148 | 149 | uint32_t index = (letter - font_p->start_ascii) * font_p->height_row * font_p->width_byte; 150 | return &font_p->bitmaps_a[index]; 151 | } 152 | 153 | /** 154 | * Get the width of a letter in a font 155 | * @param font_p pointer to a font 156 | * @param letter a letter 157 | * @return the width of a letter 158 | */ 159 | uint8_t font_get_width(const font_t * font_p, uint8_t letter) 160 | { 161 | if(letter < font_p->start_ascii) return 0; 162 | 163 | letter -= font_p->start_ascii; 164 | uint8_t w = 0; 165 | if(letter < font_p->letter_cnt) { 166 | w = font_p->fixed_width != 0 ? font_p->fixed_width : 167 | font_p->width_bit_a[letter]; 168 | } 169 | 170 | return w; 171 | } 172 | 173 | /********************** 174 | * STATIC FUNCTIONS 175 | **********************/ 176 | 177 | #endif /*USE_FONT*/ 178 | -------------------------------------------------------------------------------- /gfx/font.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file font.h 3 | * 4 | */ 5 | 6 | #ifndef FONT_H 7 | #define FONT_H 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | 14 | /********************* 15 | * INCLUDES 16 | *********************/ 17 | #include "../../misc_conf.h" 18 | #if USE_FONT != 0 19 | 20 | #include 21 | #include 22 | 23 | /********************* 24 | * DEFINES 25 | *********************/ 26 | 27 | /********************** 28 | * TYPEDEFS 29 | **********************/ 30 | 31 | typedef enum 32 | { 33 | #if USE_FONT_DEJAVU_8 != 0 34 | FONT_DEJAVU_8, 35 | #endif 36 | #if USE_FONT_DEJAVU_10 != 0 37 | FONT_DEJAVU_10, 38 | #endif 39 | #if USE_FONT_DEJAVU_14 != 0 40 | FONT_DEJAVU_14, 41 | #endif 42 | #if USE_FONT_DEJAVU_20 != 0 43 | FONT_DEJAVU_20, 44 | #endif 45 | #if USE_FONT_DEJAVU_30 != 0 46 | FONT_DEJAVU_30, 47 | #endif 48 | #if USE_FONT_DEJAVU_40 != 0 49 | FONT_DEJAVU_40, 50 | #endif 51 | #if USE_FONT_DEJAVU_60 != 0 52 | FONT_DEJAVU_60, 53 | #endif 54 | #if USE_FONT_DEJAVU_80 != 0 55 | FONT_DEJAVU_80, 56 | #endif 57 | #if USE_FONT_DEJAVU_120 != 0 58 | FONT_DEJAVU_120, 59 | #endif 60 | #if USE_FONT_SYMBOL_30 != 0 61 | FONT_SYMBOL_30, 62 | #endif 63 | #if USE_FONT_SYMBOL_60 != 0 64 | FONT_SYMBOL_60, 65 | #endif 66 | 67 | /*Insert the user defined font names*/ 68 | #ifdef FONT_NEW_NAMES 69 | FONT_NEW_NAMES 70 | #endif 71 | 72 | FONT_NAME_NUM, 73 | }font_name_t; 74 | 75 | typedef struct 76 | { 77 | uint8_t letter_cnt; 78 | uint8_t start_ascii; 79 | uint8_t width_byte; 80 | uint8_t height_row; 81 | uint8_t fixed_width; 82 | const uint8_t * width_bit_a; 83 | const uint8_t * bitmaps_a; 84 | }font_t; 85 | 86 | /********************** 87 | * GLOBAL PROTOTYPES 88 | **********************/ 89 | 90 | /** 91 | * Initialize the built-in fonts 92 | */ 93 | void font_init(void); 94 | 95 | /** 96 | * Create a pair from font name and font dsc. get function. After it 'font_get' can be used for this font 97 | * @param name name of the font 98 | * @param dsc_get_fp the font descriptor get function 99 | */ 100 | void font_add(font_name_t name, const font_t * (*dsc_get_fp)(void)); 101 | 102 | /** 103 | * Get the font from its id 104 | * @param font_id: the id of a font (an element of font_types_t enum) 105 | * @return pointer to a font descriptor 106 | */ 107 | const font_t * font_get(font_name_t font_id); 108 | 109 | 110 | /** 111 | * Return with the bitmap of a font. 112 | * @param font_p pointer to a font 113 | * @param letter a letter 114 | * @return pointer to the bitmap of the letter 115 | */ 116 | const uint8_t * font_get_bitmap(const font_t * font_p, uint8_t letter); 117 | 118 | /** 119 | * Get the height of a font 120 | * @param font_p pointer to a font 121 | * @return the height of a font 122 | */ 123 | static inline uint8_t font_get_height(const font_t * font_p) 124 | { 125 | return font_p->height_row; 126 | } 127 | 128 | 129 | /** 130 | * Get the width of a letter in a font 131 | * @param font_p pointer to a font 132 | * @param letter a letter 133 | * @return the width of a letter 134 | */ 135 | uint8_t font_get_width(const font_t * font_p, uint8_t letter); 136 | 137 | 138 | /********************** 139 | * MACROS 140 | **********************/ 141 | 142 | #endif /*USE_FONT*/ 143 | 144 | #ifdef __cplusplus 145 | } /* extern "C" */ 146 | #endif 147 | 148 | 149 | #endif 150 | -------------------------------------------------------------------------------- /gfx/fonts/dejavu_10.h: -------------------------------------------------------------------------------- 1 | #ifndef DEJAVU_10_H 2 | #define DEJAVU_10_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | /*Use ISO8859-1 encoding in the IDE*/ 9 | 10 | #include "../../../misc_conf.h" 11 | #if USE_FONT_DEJAVU_10 != 0 12 | 13 | 14 | #include 15 | #include "../font.h" 16 | 17 | 18 | const font_t * dejavu_10_get_dsc(void); 19 | 20 | #endif 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /gfx/fonts/dejavu_120.h: -------------------------------------------------------------------------------- 1 | #ifndef DEJAVU_120_H 2 | #define DEJAVU_120_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | 9 | /*Use ISO8859-1 encoding in the IDE*/ 10 | 11 | #include "../../../misc_conf.h" 12 | #if USE_FONT_DEJAVU_120 != 0 13 | 14 | 15 | #include 16 | #include "../font.h" 17 | 18 | 19 | const font_t * dejavu_120_get_dsc(void); 20 | 21 | #endif 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /gfx/fonts/dejavu_14.h: -------------------------------------------------------------------------------- 1 | #ifndef DEJAVU_14_H 2 | #define DEJAVU_14_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | 9 | /*Use ISO8859-1 encoding in the IDE*/ 10 | 11 | #include "../../../misc_conf.h" 12 | #if USE_FONT_DEJAVU_14 != 0 13 | 14 | 15 | #include 16 | #include "../font.h" 17 | 18 | 19 | const font_t * dejavu_14_get_dsc(void); 20 | 21 | #endif 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /gfx/fonts/dejavu_20.h: -------------------------------------------------------------------------------- 1 | #ifndef DEJAVU_20_H 2 | #define DEJAVU_20_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | 9 | /*Use ISO8859-1 encoding in the IDE*/ 10 | 11 | #include "../../../misc_conf.h" 12 | #if USE_FONT_DEJAVU_20 != 0 13 | 14 | 15 | #include 16 | #include "../font.h" 17 | 18 | 19 | const font_t * dejavu_20_get_dsc(void); 20 | 21 | #endif 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /gfx/fonts/dejavu_30.h: -------------------------------------------------------------------------------- 1 | #ifndef DEJAVU_30_H 2 | #define DEJAVU_30_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | 9 | /*Use ISO8859-1 encoding in the IDE*/ 10 | 11 | #include "../../../misc_conf.h" 12 | #if USE_FONT_DEJAVU_30 != 0 13 | 14 | 15 | #include 16 | #include "../font.h" 17 | 18 | 19 | const font_t * dejavu_30_get_dsc(void); 20 | 21 | #endif 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /gfx/fonts/dejavu_40.h: -------------------------------------------------------------------------------- 1 | #ifndef DEJAVU_40_H 2 | #define DEJAVU_40_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | 9 | /*Use ISO8859-1 encoding in the IDE*/ 10 | 11 | #include "../../../misc_conf.h" 12 | #if USE_FONT_DEJAVU_40 != 0 13 | 14 | 15 | #include 16 | #include "../font.h" 17 | 18 | 19 | const font_t * dejavu_40_get_dsc(void); 20 | 21 | #endif 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /gfx/fonts/dejavu_60.h: -------------------------------------------------------------------------------- 1 | #ifndef DEJAVU_60_H 2 | #define DEJAVU_60_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | 9 | /*Use ISO8859-1 encoding in the IDE*/ 10 | 11 | #include "../../../misc_conf.h" 12 | #if USE_FONT_DEJAVU_60 != 0 13 | 14 | 15 | #include 16 | #include "../font.h" 17 | 18 | 19 | const font_t * dejavu_60_get_dsc(void); 20 | 21 | #endif 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /gfx/fonts/dejavu_8.h: -------------------------------------------------------------------------------- 1 | #ifndef DEJAVU_8_H 2 | #define DEJAVU_8_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | 9 | /*Use ISO8859-1 encoding in the IDE*/ 10 | 11 | #include "../../../misc_conf.h" 12 | #if USE_FONT_DEJAVU_8 != 0 13 | 14 | 15 | #include 16 | #include "../font.h" 17 | 18 | 19 | const font_t * dejavu_8_get_dsc(void); 20 | 21 | #endif 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /gfx/fonts/dejavu_80.h: -------------------------------------------------------------------------------- 1 | #ifndef DEJAVU_80_H 2 | #define DEJAVU_80_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | 9 | /*Use ISO8859-1 encoding in the IDE*/ 10 | #include "../../../misc_conf.h" 11 | #if USE_FONT_DEJAVU_80 != 0 12 | 13 | 14 | #include 15 | #include "../font.h" 16 | const font_t * dejavu_80_get_dsc(void); 17 | 18 | #endif 19 | 20 | #ifdef __cplusplus 21 | } /* extern "C" */ 22 | #endif 23 | 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /gfx/fonts/symbol_30.h: -------------------------------------------------------------------------------- 1 | #ifndef SYMBOL_30_H 2 | #define SYMBOL_30_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | 9 | /*Use ISO8859-1 encoding in the IDE*/ 10 | #include "../../../misc_conf.h" 11 | #if USE_FONT_SYMBOL_30 != 0 12 | 13 | #include 14 | #include "../font.h" 15 | 16 | const font_t * symbol_30_get_dsc(void); 17 | 18 | #endif 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /gfx/fonts/symbol_60.h: -------------------------------------------------------------------------------- 1 | #ifndef SYMBOL_60_H 2 | #define SYMBOL_60_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | 9 | /*Use ISO8859-1 encoding in the IDE*/ 10 | #include "../../../misc_conf.h" 11 | #if USE_FONT_SYMBOL_60 != 0 12 | 13 | #include 14 | #include "../font.h" 15 | 16 | const font_t * symbol_60_get_dsc(void); 17 | 18 | #endif 19 | 20 | #ifdef __cplusplus 21 | } /* extern "C" */ 22 | #endif 23 | 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /gfx/fonts/symbol_def.h: -------------------------------------------------------------------------------- 1 | #ifndef SYMBOL_DEF_H 2 | #define SYMBOL_DEF_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | 9 | /*Use ISO8859-1 encoding in the IDE*/ 10 | #if USE_FONT_SYMBOL_30 != 0 || USE_FONT_SYMBOL_60 != 0 11 | 12 | #define SYMBOL_PLAY "Z" 13 | #define SYMBOL_STOP "[" 14 | #define SYMBOL_PAUSE "|" 15 | #define SYMBOL_PREV "]" 16 | #define SYMBOL_NEXT "^" 17 | #define SYMBOL_SPMUTE "_" 18 | #define SYMBOL_SPUNMUTE "`" 19 | #define SYMBOL_DRIVE "a" 20 | #define SYMBOL_FILE "b" 21 | #define SYMBOL_FOLDER "c" 22 | #define SYMBOL_DELETE "d" 23 | #define SYMBOL_SAVE "e" 24 | #define SYMBOL_EDIT "f" 25 | #define SYMBOL_OK "g" 26 | #define SYMBOL_CLOSE "h" 27 | #define SYMBOL_DOWN "i" 28 | #define SYMBOL_LEFT "j" 29 | #define SYMBOL_RIGHT "k" 30 | #define SYMBOL_UP "l" 31 | #define SYMBOL_BT "m" 32 | #define SYMBOL_THERM "n" 33 | #define SYMBOL_GPS "o" 34 | #define SYMBOL_WARN "p" 35 | #define SYMBOL_INFO "q" 36 | #define SYMBOL_BATT1 "r" 37 | #define SYMBOL_BATT2 "s" 38 | #define SYMBOL_BATT3 "t" 39 | #define SYMBOL_BATT4 "u" 40 | #define SYMBOL_BATTCH "v" 41 | #define SYMBOL_HELP "w" 42 | #define SYMBOL_POWER "x" 43 | #define SYMBOL_SETUP "y" 44 | #define SYMBOL_WIFI "z" 45 | 46 | #endif 47 | 48 | #ifdef __cplusplus 49 | } /* extern "C" */ 50 | #endif 51 | 52 | 53 | #endif /*SYMBOL_DEF_H*/ 54 | -------------------------------------------------------------------------------- /gfx/text.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file font.c 3 | * 4 | */ 5 | 6 | /********************* 7 | * INCLUDES 8 | *********************/ 9 | #include "../../misc_conf.h" 10 | #if USE_TEXT != 0 11 | 12 | #include "text.h" 13 | #include "../math/math_base.h" 14 | 15 | /********************* 16 | * DEFINES 17 | *********************/ 18 | #define TXT_NO_BREAK_FOUND UINT16_MAX 19 | 20 | /********************** 21 | * TYPEDEFS 22 | **********************/ 23 | 24 | /********************** 25 | * STATIC PROTOTYPES 26 | **********************/ 27 | static bool txt_is_break_char(char letter); 28 | 29 | /********************** 30 | * STATIC VARIABLES 31 | **********************/ 32 | 33 | /********************** 34 | * MACROS 35 | **********************/ 36 | 37 | /********************** 38 | * GLOBAL FUNCTIONS 39 | **********************/ 40 | 41 | /** 42 | * Get size of a text 43 | * @param size_res pointer to a 'point_t' variable to store the result 44 | * @param text pointer to a text 45 | * @param font pinter to font of the text 46 | * @param letter_space letter space of the text 47 | * @param line_space line space of the text 48 | * @param flags settings for the text from 'txt_flag_t' enum 49 | * @param max_width max with of the text (break the lines to fit this size) Set CORD_MAX to avoid line breaks 50 | */ 51 | void txt_get_size(point_t * size_res, const char * text, const font_t * font, 52 | cord_t letter_space, cord_t line_space, cord_t max_width, txt_flag_t flag) 53 | { 54 | size_res->x = 0; 55 | size_res->y = 0; 56 | 57 | if(text == NULL) return; 58 | if(font == NULL) return; 59 | 60 | if(flag & TXT_FLAG_EXPAND) max_width = CORD_MAX; 61 | 62 | uint32_t line_start = 0; 63 | uint32_t new_line_start = 0; 64 | cord_t act_line_length; 65 | uint8_t letter_height = font_get_height(font) >> FONT_ANTIALIAS; 66 | 67 | /*Calc. the height and longest line*/ 68 | while (text[line_start] != '\0') { 69 | new_line_start += txt_get_next_line(&text[line_start], font, letter_space, max_width, flag); 70 | size_res->y += letter_height ; 71 | size_res->y += line_space; 72 | 73 | /*Calculate the the longest line*/ 74 | act_line_length = txt_get_width(&text[line_start], new_line_start - line_start, 75 | font, letter_space, flag); 76 | 77 | size_res->x = MATH_MAX(act_line_length, size_res->x); 78 | line_start = new_line_start; 79 | } 80 | 81 | if(line_start != 0 && (text[line_start - 1] == '\n' || text[line_start - 1] == '\r')) { 82 | size_res->y += letter_height + line_space; 83 | } 84 | 85 | /*Correction with the last line space or set the height manually if the text is empty*/ 86 | if(size_res->y == 0) size_res->y = letter_height; 87 | else size_res->y -= line_space; 88 | 89 | } 90 | 91 | /** 92 | * Get the next line of text. Check line length and break chars too. 93 | * @param txt a '\0' terminated string 94 | * @param font pointer to a font 95 | * @param letter_space letter space 96 | * @param max_width max with of the text (break the lines to fit this size) Set CORD_MAX to avoid line breaks 97 | * @param flags settings for the text from 'txt_flag_type' enum 98 | * @return the index of the first char of the new line 99 | */ 100 | uint16_t txt_get_next_line(const char * txt, const font_t * font, 101 | cord_t letter_space, cord_t max_width, txt_flag_t flag) 102 | { 103 | if(txt == NULL) return 0; 104 | if(font == NULL) return 0; 105 | 106 | if(flag & TXT_FLAG_EXPAND) max_width = CORD_MAX; 107 | 108 | uint32_t i = 0; 109 | cord_t act_l = 0; 110 | uint16_t last_break = TXT_NO_BREAK_FOUND; 111 | txt_cmd_state_t cmd_state = TXT_CMD_STATE_WAIT; 112 | 113 | while(txt[i] != '\0') { 114 | 115 | /*Handle the recolor command*/ 116 | if((flag & TXT_FLAG_RECOLOR) != 0) { 117 | if(txt_is_cmd(&cmd_state, txt[i]) != false) { 118 | i++; /*Skip the letter is it is part of a command*/ 119 | continue; 120 | } 121 | } 122 | /*Check for new line chars*/ 123 | if((flag & TXT_FLAG_NO_BREAK) == 0 && (txt[i] == '\n' || txt[i] == '\r')) { 124 | /*Handle \n\r and \r\n as well*/ 125 | if(txt[i] == '\n' && txt[i + 1] == '\r') { 126 | i++; 127 | } else if(txt[i] == '\r' && txt[i + 1] == '\n') { 128 | i++; 129 | } 130 | return i+1; /*Return with the first letter of the next line*/ 131 | 132 | } else { /*Check the actual length*/ 133 | act_l += font_get_width(font, txt[i]) >> FONT_ANTIALIAS; 134 | 135 | /*If the txt is too long then finish, this is the line end*/ 136 | if(act_l > max_width) { 137 | /*If already a break character is found, then break there*/ 138 | if(last_break != TXT_NO_BREAK_FOUND && txt_is_break_char(txt[i]) == false) { 139 | i = last_break; 140 | } 141 | 142 | while(txt[i] == ' ') i++; 143 | 144 | /* Do not let to return without doing nothing. 145 | * Find at least one character */ 146 | if(i == 0) i++; 147 | 148 | return i; 149 | } 150 | /*If this char still can fit to this line then check if 151 | * txt can be broken here later */ 152 | else if(txt_is_break_char(txt[i])) { 153 | last_break = i; 154 | last_break++;/*Go to the next char, the break char stays in this line*/ 155 | } 156 | } 157 | 158 | act_l += letter_space; 159 | i++; 160 | } 161 | 162 | return i; 163 | } 164 | 165 | /** 166 | * Give the length of a text with a given font 167 | * @param txt a '\0' terminate string 168 | * @param char_num number of characters in 'txt' 169 | * @param font pointer to a font 170 | * @param letter_space letter space 171 | * @param flags settings for the text from 'txt_flag_t' enum 172 | * @return length of a char_num long text 173 | */ 174 | cord_t txt_get_width(const char * txt, uint16_t char_num, 175 | const font_t * font, cord_t letter_space, txt_flag_t flag) 176 | { 177 | if(txt == NULL) return 0; 178 | if(font == NULL) return 0; 179 | 180 | uint16_t i; 181 | cord_t len = 0; 182 | txt_cmd_state_t cmd_state = TXT_CMD_STATE_WAIT; 183 | 184 | if(char_num != 0) { 185 | for(i = 0; i < char_num; i++) { 186 | if((flag & TXT_FLAG_RECOLOR) != 0) { 187 | if(txt_is_cmd(&cmd_state, txt[i]) != false) { 188 | continue; 189 | } 190 | } 191 | len += font_get_width(font, txt[i]) >> FONT_ANTIALIAS; 192 | len += letter_space; 193 | } 194 | 195 | /*Trim closing spaces */ 196 | for(i = char_num - 1; i > 0; i--) { 197 | if(txt[i] == ' ') { 198 | len -= font_get_width(font, txt[i]) >> FONT_ANTIALIAS; 199 | len -= letter_space; 200 | } else { 201 | break; 202 | } 203 | } 204 | } 205 | 206 | return len; 207 | } 208 | 209 | /** 210 | * Check next character in a string and decide if the character is part of the command or not 211 | * @param state pointer to a txt_cmd_state_t variable which stores the current state of command processing 212 | * (Initied. to TXT_CMD_STATE_WAIT ) 213 | * @param c the current character 214 | * @return true: the character is part of a command and should not be written, 215 | * false: the character should be written 216 | */ 217 | bool txt_is_cmd(txt_cmd_state_t * state, char c) 218 | { 219 | bool ret = false; 220 | 221 | if(c == TXT_RECOLOR_CMD) { 222 | if(*state == TXT_CMD_STATE_WAIT) { /*Start char*/ 223 | *state = TXT_CMD_STATE_PAR; 224 | ret = true; 225 | } else if(*state == TXT_CMD_STATE_PAR) { /*Other start char in parameter is escaped cmd. char */ 226 | *state = TXT_CMD_STATE_WAIT; 227 | }else if(*state == TXT_CMD_STATE_IN) { /*Command end */ 228 | *state = TXT_CMD_STATE_WAIT; 229 | ret = true; 230 | } 231 | } 232 | 233 | /*Skip the color parameter and wait the space after it*/ 234 | if(*state == TXT_CMD_STATE_PAR) { 235 | if(c == ' ') { 236 | *state = TXT_CMD_STATE_IN; /*After the parameter the text is in the command*/ 237 | } 238 | ret = true; 239 | } 240 | 241 | return ret; 242 | } 243 | 244 | /********************** 245 | * STATIC FUNCTIONS 246 | **********************/ 247 | 248 | /** 249 | * Test if char is break char or not (a text can broken here or not) 250 | * @param letter a letter 251 | * @return false: 'letter' is not break char 252 | */ 253 | static bool txt_is_break_char(char letter) 254 | { 255 | uint8_t i; 256 | bool ret = false; 257 | 258 | /*Compare the letter to TXT_BREAK_CHARS*/ 259 | for(i = 0; TXT_BREAK_CHARS[i] != '\0'; i++) { 260 | if(letter == TXT_BREAK_CHARS[i]) { 261 | ret = true; /*If match then it is break char*/ 262 | break; 263 | } 264 | } 265 | 266 | return ret; 267 | } 268 | 269 | #endif /*USE_TEXT*/ 270 | -------------------------------------------------------------------------------- /gfx/text.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file text.h 3 | * 4 | */ 5 | 6 | #ifndef TEXT_H 7 | #define TEXT_H 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | /********************* 14 | * INCLUDES 15 | *********************/ 16 | #include "../../misc_conf.h" 17 | #if USE_FONT != 0 18 | 19 | #include 20 | #include "area.h" 21 | #include "font.h" 22 | #include "area.h" 23 | 24 | /********************* 25 | * DEFINES 26 | *********************/ 27 | #define TXT_RECOLOR_CMD '#' 28 | 29 | /********************** 30 | * TYPEDEFS 31 | **********************/ 32 | typedef enum 33 | { 34 | TXT_FLAG_NONE = 0x00, 35 | TXT_FLAG_RECOLOR = 0x01, /*Enable parsing of recolor command*/ 36 | TXT_FLAG_EXPAND = 0x02, /*Ignore width (Used by the library)*/ 37 | TXT_FLAG_NO_BREAK = 0x04, /*Ignore line breaks (Used by the library)*/ 38 | }txt_flag_t; 39 | 40 | typedef enum 41 | { 42 | TXT_CMD_STATE_WAIT, 43 | TXT_CMD_STATE_PAR, 44 | TXT_CMD_STATE_IN, 45 | }txt_cmd_state_t; 46 | 47 | /********************** 48 | * GLOBAL PROTOTYPES 49 | **********************/ 50 | 51 | /** 52 | * Get size of a text 53 | * @param size_res pointer to a 'point_t' variable to store the result 54 | * @param text pointer to a text 55 | * @param font pinter to font of the text 56 | * @param letter_space letter space of the text 57 | * @param line_space line space of the text 58 | * @param flags settings for the text from 'txt_flag_t' enum 59 | * @param max_width max with of the text (break the lines to fit this size) Set CORD_MAX to avoid line breaks 60 | */ 61 | void txt_get_size(point_t * size_res, const char * text, const font_t * font, 62 | cord_t letter_space, cord_t line_space, cord_t max_width, txt_flag_t flag); 63 | 64 | /** 65 | * Get the next line of text. Check line length and break chars too. 66 | * @param txt a '\0' terminated string 67 | * @param font_p pointer to a font 68 | * @param letter_space letter space 69 | * @param max_width max with of the text (break the lines to fit this size) Set CORD_MAX to avoid line breaks 70 | * @param flags settings for the text from 'txt_flag_t' enum 71 | * @return the index of the first char of the new line 72 | */ 73 | uint16_t txt_get_next_line(const char * txt, const font_t * font_p, 74 | cord_t letter_space, cord_t max_l, txt_flag_t flag); 75 | 76 | /** 77 | * Give the length of a text with a given font 78 | * @param txt a '\0' terminate string 79 | * @param char_num number of characters in 'txt' 80 | * @param font_p pointer to a font 81 | * @param letter_space letter space 82 | * @param flags settings for the text from 'txt_flag_t' enum 83 | * @return length of a char_num long text 84 | */ 85 | cord_t txt_get_width(const char * txt, uint16_t char_num, 86 | const font_t * font_p, cord_t letter_space, txt_flag_t flag); 87 | 88 | /** 89 | * Check next character in a string and decide if te character is part of the command or not 90 | * @param state pointer to a txt_cmd_state_t variable which stores the current state of command processing 91 | * @param c the current character 92 | * @return true: the character is part of a command and should not be written, 93 | * false: the character should be written 94 | */ 95 | bool txt_is_cmd(txt_cmd_state_t * state, char c); 96 | 97 | /********************** 98 | * MACROS 99 | **********************/ 100 | 101 | #endif /*USE_TEXT*/ 102 | 103 | #ifdef __cplusplus 104 | } /* extern "C" */ 105 | #endif 106 | 107 | 108 | #endif 109 | -------------------------------------------------------------------------------- /licence.txt: -------------------------------------------------------------------------------- 1 | MIT licence 2 | Copyright (c) 2016 Gábor Kiss-Vámosi 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 9 | -------------------------------------------------------------------------------- /math/math_base.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file math_base.h 3 | * 4 | */ 5 | 6 | #ifndef MATH_BASE_H 7 | #define MATH_BASE_H 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | 14 | /********************* 15 | * INCLUDES 16 | *********************/ 17 | #include "../../misc_conf.h" 18 | #if USE_MATH_BASE != 0 19 | 20 | /********************* 21 | * DEFINES 22 | *********************/ 23 | 24 | #define MATH_MIN(a,b) (ab?a:b) 26 | #define MATH_ABS(x) ((x)>0?(x):(-(x))) 27 | 28 | /********************** 29 | * TYPEDEFS 30 | **********************/ 31 | 32 | /********************** 33 | * GLOBAL PROTOTYPES 34 | **********************/ 35 | 36 | /********************** 37 | * MACROS 38 | **********************/ 39 | 40 | #endif /*USE_MATH_BASE*/ 41 | 42 | #ifdef __cplusplus 43 | } /* extern "C" */ 44 | #endif 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /math/trigo.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file trigo.c 3 | * Basic trigonometrical integer functions 4 | */ 5 | 6 | /********************* 7 | * INCLUDES 8 | *********************/ 9 | #include "../../misc_conf.h" 10 | #if USE_TRIGO != 0 11 | 12 | #include "trigo.h" 13 | 14 | /********************* 15 | * DEFINES 16 | *********************/ 17 | 18 | /********************** 19 | * TYPEDEFS 20 | **********************/ 21 | 22 | /********************** 23 | * STATIC PROTOTYPES 24 | **********************/ 25 | 26 | /********************** 27 | * STATIC VARIABLES 28 | **********************/ 29 | static int16_t sin0_90_table[] = 30 | { 31 | 0, 572, 1144, 1715, 2286, 2856, 3425, 3993, 4560, 5126, 32 | 5690, 6252, 6813, 7371, 7927, 8481, 9032, 9580, 10126, 10668, 33 | 11207, 11743, 12275, 12803, 13328, 13848, 14364, 14876, 15383, 15886, 34 | 16383, 16876, 17364, 17846, 18323, 18794, 19260, 19720, 20173, 20621, 35 | 21062, 21497, 21925, 22347, 22762, 23170, 23571, 23964, 24351, 24730, 36 | 25101, 25465, 25821, 26169, 26509, 26841, 27165, 27481, 27788, 28087, 37 | 28377, 28659, 28932, 29196, 29451, 29697, 29934, 30162, 30381, 30591, 38 | 30791, 30982, 31163, 31335, 31498, 31650, 31794, 31927, 32051, 32165, 39 | 32269, 32364, 32448, 32523, 32587, 32642, 32687, 32722, 32747, 32762 40 | }; 41 | 42 | 43 | /********************** 44 | * MACROS 45 | **********************/ 46 | 47 | /********************** 48 | * GLOBAL FUNCTIONS 49 | **********************/ 50 | 51 | /** 52 | * Return with sinus of an angle 53 | * @param angle 54 | * @return sinus of 'angle'. sin(-90) = -32767, sin(90) = 32767 55 | */ 56 | int16_t trigo_sin(int16_t angle) 57 | { 58 | int16_t ret = 0; 59 | angle = angle % 360; 60 | 61 | if(angle < 0) angle = 360 + angle; 62 | 63 | if(angle < 90){ 64 | ret = sin0_90_table[angle]; 65 | } else if(angle >= 90 && angle < 180) 66 | { 67 | angle = 179 - angle; 68 | ret = sin0_90_table[angle]; 69 | } else if(angle >= 180 && angle < 270) 70 | { 71 | angle = angle - 180; 72 | ret = - sin0_90_table[angle]; 73 | } else { /*angle >=270*/ 74 | angle = 359 - angle; 75 | ret = - sin0_90_table[angle]; 76 | } 77 | 78 | return ret; 79 | } 80 | 81 | 82 | /********************** 83 | * STATIC FUNCTIONS 84 | **********************/ 85 | 86 | #endif 87 | -------------------------------------------------------------------------------- /math/trigo.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file trig.h 3 | * Basic trigonometrical integer functions 4 | */ 5 | 6 | #ifndef TRIGO_H 7 | #define TRIGO_H 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | 14 | /********************* 15 | * INCLUDES 16 | *********************/ 17 | #include "../../misc_conf.h" 18 | #if USE_TRIGO != 0 19 | 20 | #include 21 | 22 | /********************* 23 | * DEFINES 24 | *********************/ 25 | #define TRIGO_SIN_MAX 32767 26 | 27 | /********************** 28 | * TYPEDEFS 29 | **********************/ 30 | 31 | /********************** 32 | * GLOBAL PROTOTYPES 33 | **********************/ 34 | 35 | /** 36 | * Return with sinus of an angle 37 | * @param angle 38 | * @return sinus of 'angle'. sin(-90) = -32767, sin(90) = 32767 39 | */ 40 | int16_t trigo_sin(int16_t angle); 41 | 42 | /********************** 43 | * MACROS 44 | **********************/ 45 | 46 | #endif /*USE_TRIGO*/ 47 | 48 | #ifdef __cplusplus 49 | } /* extern "C" */ 50 | #endif 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /mem/dyn_mem.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file dyn_mem.c 3 | * General and portable implementation of malloc and free. 4 | * The dynamic memory monitoring is also supported. 5 | */ 6 | 7 | /********************* 8 | * INCLUDES 9 | *********************/ 10 | #include "../../misc_conf.h" 11 | #if USE_DYN_MEM != 0 12 | 13 | #include "dyn_mem.h" 14 | #include "../math/math_base.h" 15 | #include 16 | 17 | #if DM_CUSTOM != 0 18 | #include DM_CUST_INCLUDE 19 | #endif 20 | 21 | /********************* 22 | * DEFINES 23 | *********************/ 24 | 25 | /********************** 26 | * TYPEDEFS 27 | **********************/ 28 | 29 | /*The size of this union must be 4 bytes (uint32_t)*/ 30 | typedef union 31 | { 32 | struct 33 | { 34 | uint32_t used:1; //1: if the entry is used 35 | uint32_t d_size:31; //Size off the data (1 means 4 bytes) 36 | }; 37 | uint32_t header; //The header (used + d_size) 38 | }dm_header_t; 39 | 40 | typedef struct 41 | { 42 | dm_header_t header; 43 | uint8_t first_data; //First data in entry data 44 | }dm_ent_t; 45 | 46 | /********************** 47 | * STATIC PROTOTYPES 48 | **********************/ 49 | #if DM_CUSTOM == 0 50 | static dm_ent_t * ent_get_next(dm_ent_t * act_e); 51 | static void * ent_alloc(dm_ent_t * e, uint32_t size); 52 | static dm_ent_t * ent_trunc(dm_ent_t * e, uint32_t size); 53 | #endif 54 | 55 | /********************** 56 | * STATIC VARIABLES 57 | **********************/ 58 | #if DM_CUSTOM == 0 59 | static DM_MEM_ATTR uint8_t work_mem[DM_MEM_SIZE] ; //Work memory for allocation 60 | #endif 61 | 62 | static uint32_t zero_mem; /*Give the address of this variable if 0 byte should be allocated*/ 63 | 64 | /********************** 65 | * MACROS 66 | **********************/ 67 | 68 | /********************** 69 | * GLOBAL FUNCTIONS 70 | **********************/ 71 | 72 | /** 73 | * Initiaize the dyn_mem module (work memory and other variables) 74 | */ 75 | void dm_init(void) 76 | { 77 | #if DM_CUSTOM == 0 78 | dm_ent_t * full = (dm_ent_t *)&work_mem; 79 | full->header.used = 0; 80 | /*The total mem size id reduced by the first header and the close patterns */ 81 | full->header.d_size = DM_MEM_SIZE - sizeof(dm_header_t); 82 | #endif 83 | } 84 | 85 | /** 86 | * Allocate a memory dynamically 87 | * @param size size of the memory to allocate in bytes 88 | * @return pointer to the allocated memory 89 | */ 90 | void * dm_alloc(uint32_t size) 91 | { 92 | if(size == 0) { 93 | return &zero_mem; 94 | } 95 | 96 | /*Round the size up to 4*/ 97 | if(size & 0x3 ) { 98 | size = size & (~0x3); 99 | size += 4; 100 | } 101 | 102 | void * alloc = NULL; 103 | 104 | #if DM_CUSTOM == 0 /*Use the allocation from dyn_mem*/ 105 | dm_ent_t * e = NULL; 106 | 107 | //Search for a appropriate entry 108 | do { 109 | //Get the next entry 110 | e = ent_get_next(e); 111 | 112 | //If there is next entry then try to allocate there 113 | if(e != NULL) { 114 | alloc = ent_alloc(e, size); 115 | } 116 | //End if there is not next entry OR the alloc. is successful 117 | }while(e != NULL && alloc == NULL); 118 | #else /*Use custom, user defined malloc function*/ 119 | /*Allocate a header too to store the size*/ 120 | alloc = DM_CUST_ALLOC(size + sizeof(dm_header_t)); 121 | if(alloc != NULL) { 122 | ((dm_ent_t*) alloc)->header.d_size = size; 123 | ((dm_ent_t*) alloc)->header.used = 1; 124 | alloc = &((dm_ent_t*) alloc)->first_data; 125 | } 126 | #endif 127 | 128 | #if DM_AUTO_ZERO != 0 129 | if(alloc != NULL) memset(alloc, 0, size); 130 | #endif 131 | 132 | return alloc; 133 | } 134 | 135 | /** 136 | * Free an allocated data 137 | * @param data pointer to an allocated memory 138 | */ 139 | void dm_free(const void * data) 140 | { 141 | if(data == &zero_mem) return; 142 | if(data == NULL) return; 143 | 144 | /*e points to the header*/ 145 | dm_ent_t * e = (dm_ent_t *)((uint8_t *) data - sizeof(dm_header_t)); 146 | e->header.used = 0; 147 | 148 | #if DM_CUSTOM == 0 /*Use the free from dyn_mem*/ 149 | /* Make a simple defrag. 150 | * Join the following free entries after this*/ 151 | dm_ent_t * e_next; 152 | e_next = ent_get_next(e); 153 | while(e_next != NULL) { 154 | if(e_next->header.used == 0) { 155 | e->header.d_size += e_next->header.d_size + sizeof(e->header); 156 | } else { 157 | break; 158 | } 159 | e_next = ent_get_next(e_next); 160 | } 161 | #else /*Use custom, user defined free function*/ 162 | DM_CUST_FREE(e); 163 | #endif 164 | } 165 | 166 | /** 167 | * Reallocate a memory with a new size. The old content will be kept. 168 | * @param data pointer to an allocated memory. 169 | * Its content will be copied to the new memory block and freed 170 | * @param new_size the desired new size in byte 171 | * @return pointer to the new memory 172 | */ 173 | void * dm_realloc(void * data_p, uint32_t new_size) 174 | { 175 | /*data_p could be previously freed pointer (in this case it is invalid)*/ 176 | if(data_p != NULL) { 177 | dm_ent_t * e = (dm_ent_t *)((uint8_t *) data_p - sizeof(dm_header_t)); 178 | if(e->header.used == 0) data_p = NULL; 179 | } 180 | 181 | uint32_t old_size = dm_get_size(data_p); 182 | if(old_size == new_size) return data_p; 183 | 184 | void * new_p; 185 | new_p = dm_alloc(new_size); 186 | 187 | if(new_p != NULL && data_p != NULL) { 188 | /*Copy the old data to the new. Use the smaller size*/ 189 | if(old_size != 0) { 190 | memcpy(new_p, data_p, MATH_MIN(new_size, old_size)); 191 | dm_free(data_p); 192 | } 193 | } 194 | 195 | return new_p; 196 | } 197 | 198 | /** 199 | * Join the adjacent free memory blocks 200 | */ 201 | void dm_defrag(void) 202 | { 203 | #if DM_CUSTOM == 0 204 | dm_ent_t * e_free; 205 | dm_ent_t * e_next; 206 | e_free = ent_get_next(NULL); 207 | 208 | while(1) { 209 | /*Search the next free entry*/ 210 | while(e_free != NULL) { 211 | if(e_free->header.used != 0) { 212 | e_free = ent_get_next(e_free); 213 | } else { 214 | break; 215 | } 216 | } 217 | 218 | if(e_free == NULL) return; 219 | 220 | /*Joint the following free entries to the free*/ 221 | e_next = ent_get_next(e_free); 222 | while(e_next != NULL) { 223 | if(e_next->header.used == 0) { 224 | e_free->header.d_size += e_next->header.d_size + sizeof(e_next->header); 225 | } else { 226 | break; 227 | } 228 | 229 | e_next = ent_get_next(e_next); 230 | } 231 | 232 | if(e_next == NULL) return; 233 | 234 | /*Continue from the lastly checked entry*/ 235 | e_free = e_next; 236 | } 237 | #endif 238 | } 239 | 240 | /** 241 | * Give information about the work memory of dynamic allocation 242 | * @param mon_p pointer to a dm_mon_p variable, 243 | * the result of the analysis will be stored here 244 | */ 245 | void dm_monitor(dm_mon_t * mon_p) 246 | { 247 | /*Init the data*/ 248 | memset(mon_p, 0, sizeof(dm_mon_t)); 249 | #if DM_CUSTOM == 0 250 | dm_ent_t * e; 251 | e = NULL; 252 | 253 | e = ent_get_next(e); 254 | 255 | while(e != NULL) { 256 | if(e->header.used == 0) { 257 | mon_p->cnt_free++; 258 | mon_p->size_free += e->header.d_size; 259 | if(e->header.d_size > mon_p->size_free_big) { 260 | mon_p->size_free_big = e->header.d_size; 261 | } 262 | } else { 263 | mon_p->cnt_used++; 264 | } 265 | 266 | e = ent_get_next(e); 267 | } 268 | mon_p->size_total = DM_MEM_SIZE; 269 | mon_p->pct_used = 100 - (100U * mon_p->size_free) / mon_p->size_total; 270 | mon_p->pct_frag = (uint32_t)mon_p->size_free_big * 100U / mon_p->size_free; 271 | mon_p->pct_frag = 100 - mon_p->pct_frag; 272 | #endif 273 | } 274 | 275 | /** 276 | * Give the size of an allocated memory 277 | * @param data pointer to an allocated memory 278 | * @return the size of data memory in bytes 279 | */ 280 | uint32_t dm_get_size(void * data) 281 | { 282 | if(data == NULL) return 0; 283 | if(data == &zero_mem) return 0; 284 | 285 | dm_ent_t * e = (dm_ent_t *)((uint8_t *) data - sizeof(dm_header_t)); 286 | 287 | return e->header.d_size; 288 | } 289 | /********************** 290 | * STATIC FUNCTIONS 291 | **********************/ 292 | 293 | #if DM_CUSTOM == 0 294 | /** 295 | * Give the next entry after 'act_e' 296 | * @param act_e pointer to an entry 297 | * @return pointer to an entry after 'act_e' 298 | */ 299 | static dm_ent_t * ent_get_next(dm_ent_t * act_e) 300 | { 301 | dm_ent_t * next_e = NULL; 302 | 303 | if(act_e == NULL) { /*NULL means: get the first entry*/ 304 | next_e = (dm_ent_t * ) work_mem; 305 | } 306 | else /*Get the next entry */ 307 | { 308 | uint8_t * data = &act_e->first_data; 309 | next_e = (dm_ent_t * )&data[act_e->header.d_size]; 310 | 311 | if(&next_e->first_data >= &work_mem[DM_MEM_SIZE]) next_e = NULL; 312 | } 313 | 314 | return next_e; 315 | } 316 | 317 | 318 | /** 319 | * Try to do the real allocation with a given size 320 | * @param e try to allocate to this entry 321 | * @param size size of the new memory in bytes 322 | * @return pointer to the allocated memory or NULL if not enough memory in the entry 323 | */ 324 | static void * ent_alloc(dm_ent_t * e, uint32_t size) 325 | { 326 | void * alloc = NULL; 327 | 328 | /*If the memory is free and big enough ten use it */ 329 | if(e->header.used == 0 && e->header.d_size >= size) { 330 | /*Truncate the entry to the desired size */ 331 | ent_trunc(e, size), 332 | 333 | e->header.used = 1; 334 | 335 | /*Save the allocated data*/ 336 | alloc = &e->first_data; 337 | } 338 | 339 | return alloc; 340 | } 341 | 342 | /** 343 | * Truncate the data of entry to the given size 344 | * @param e Pointer to an entry 345 | * @param size new size in bytes 346 | * @return the new entry created from the remaining memory 347 | */ 348 | static dm_ent_t * ent_trunc(dm_ent_t * e, uint32_t size) 349 | { 350 | dm_ent_t * new_e; 351 | 352 | /*Do let empty space only for a header withot data*/ 353 | if(e->header.d_size == size + sizeof(dm_header_t)) { 354 | size += sizeof(dm_header_t); 355 | } 356 | 357 | /* Create the new entry after the current if there is space for it */ 358 | if(e->header.d_size != size) { 359 | uint8_t * e_data = &e->first_data; 360 | dm_ent_t * new_e = (dm_ent_t *)&e_data[size]; 361 | new_e->header.used = 0; 362 | new_e->header.d_size = e->header.d_size - size - sizeof(dm_header_t); 363 | } 364 | 365 | /* Set the new size for the original entry */ 366 | e->header.d_size = size; 367 | new_e = e; 368 | 369 | return new_e; 370 | } 371 | 372 | #endif /*DM_CUSTOM == 0*/ 373 | 374 | #endif 375 | -------------------------------------------------------------------------------- /mem/dyn_mem.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file dyn_mem.h 3 | * 4 | */ 5 | 6 | #ifndef DYN_MEM_H 7 | #define DYN_MEM_H 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | 14 | /********************* 15 | * INCLUDES 16 | *********************/ 17 | #include "../../misc_conf.h" 18 | #if USE_DYN_MEM != 0 19 | 20 | #include 21 | #include 22 | 23 | 24 | /********************* 25 | * DEFINES 26 | *********************/ 27 | 28 | /********************** 29 | * TYPEDEFS 30 | **********************/ 31 | 32 | typedef struct 33 | { 34 | uint32_t cnt_free; 35 | uint32_t cnt_used; 36 | uint32_t size_free; 37 | uint32_t size_total; 38 | uint32_t size_free_big; 39 | uint8_t pct_frag; 40 | uint8_t pct_used; 41 | }dm_mon_t; 42 | 43 | 44 | /********************** 45 | * GLOBAL PROTOTYPES 46 | **********************/ 47 | 48 | 49 | /** 50 | * Initiaize the dyn_mem module (work memory and other variables) 51 | */ 52 | void dm_init(void); 53 | 54 | /** 55 | * Allocate a memory dynamically 56 | * @param size size of the memory to allocate in bytes 57 | * @return pointer to the allocated memory 58 | */ 59 | void * dm_alloc(uint32_t size); 60 | 61 | /** 62 | * Free an allocated data 63 | * @param data pointer to an allocated memory 64 | */ 65 | void dm_free(const void * data); 66 | 67 | /** 68 | * Reallocate a memory with a new size. The old content will be kept. 69 | * @param data pointer to an allocated memory. 70 | * Its content will be copied to the new memory block and freed 71 | * @param new_size the desired new size in byte 72 | * @return pointer to the new memory 73 | */ 74 | void * dm_realloc(void * data_p, uint32_t new_size); 75 | 76 | /** 77 | * Join the adjacent free memory blocks 78 | */ 79 | void dm_defrag(void); 80 | 81 | /** 82 | * Give information about the work memory of dynamic allocation 83 | * @param mon_p pointer to a dm_mon_p variable, 84 | * the result of the analysis will be stored here 85 | */ 86 | void dm_monitor(dm_mon_t * mon_p); 87 | 88 | /** 89 | * Give the size of an allocated memory 90 | * @param data pointer to an allocated memory 91 | * @return the size of data memory in bytes 92 | */ 93 | uint32_t dm_get_size(void * data); 94 | 95 | /********************** 96 | * MACROS 97 | **********************/ 98 | 99 | #define dm_assert(p) {if(p == NULL) {while(1);}} 100 | 101 | #endif /*USE_DYN_MEM*/ 102 | 103 | #ifdef __cplusplus 104 | } /* extern "C" */ 105 | #endif 106 | 107 | #endif /*DYN_MEM_H*/ 108 | 109 | -------------------------------------------------------------------------------- /mem/dyn_mem_defr.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file dyn_mem.c 3 | * Implementation of special memory allocation which 4 | * always provides 0 % fragmentation. 5 | * It is NOT COMAPTIBLE with normal malloc/free. 6 | */ 7 | 8 | /* 9 | * !!!IMPORTANT!!!! 10 | * It is NOT COMAPTIBLE with normal malloc/free. 11 | * The dmd_alloc function can allocate a new memory and give pointer to it 12 | * but this pointer is special: 13 | * - to store this special pointer use the dp tag (means Dynamic Pointer) 14 | * e.g. int dp * x = dmd_alloc(sizeof(int)) (and not simply int * x) 15 | * - to convert this pointer to normal pointer use the da() tag (means Dynamic Access) 16 | * e.g. *da(x) = 5; 17 | * - never store the pointer converted by da(), only use it locally 18 | * 19 | * How dose it works? 20 | * This type of allocation separates the memory entry descriptors 21 | * from the allocated memory chunks. The descriptors are located 22 | * at the end of memory and contains a pointer to their memory chunk. 23 | * dmd_alloc gives a pointer to a descriptor which stores the pointer 24 | * of the memory chunk. So it is a void ** and NOT void *. 25 | * That is why it is not compatible with malloc. 26 | * Because the memory chunk addressed are not stored by the user 27 | * they can be moved to achieve 0 fragmentation. 28 | */ 29 | 30 | /********************* 31 | * INCLUDES 32 | *********************/ 33 | #include "../../misc_conf.h" 34 | #if USE_DYN_MEM_DEFR != 0 35 | 36 | #include "dyn_mem_defr.h" 37 | #include "../math/math_base.h" 38 | #include 39 | 40 | /********************* 41 | * DEFINES 42 | *********************/ 43 | 44 | /********************** 45 | * TYPEDEFS 46 | **********************/ 47 | 48 | 49 | /********************** 50 | * STATIC PROTOTYPES 51 | **********************/ 52 | 53 | static dmd_ent_t * ent_get_next(dmd_ent_t * act_e); 54 | static dmd_ent_t * ent_get_next_ord(dmd_ent_t * e); 55 | static void * ent_alloc(dmd_ent_t * e, uint32_t size); 56 | static dmd_ent_t * ent_trunc(dmd_ent_t * e, uint32_t size); 57 | 58 | /********************** 59 | * STATIC VARIABLES 60 | **********************/ 61 | static DM_MEM_ATTR uint8_t work_mem[DM_MEM_SIZE] ; //Work memory for allocation 62 | static uint32_t zero_mem; /*Give the address of this variable if 0 byte should be allocated*/ 63 | static dmd_ent_t * master_e; /*The 1 big free entry*/ 64 | static dmd_ent_t * last_e; /*The last entry*/ 65 | 66 | /********************** 67 | * MACROS 68 | **********************/ 69 | 70 | /********************** 71 | * GLOBAL FUNCTIONS 72 | **********************/ 73 | 74 | /** 75 | * Initiaize the dyn_mem module (work memory and other variables) 76 | */ 77 | void dmd_init(void) 78 | { 79 | dmd_ent_t * e = (dmd_ent_t *)&work_mem[DM_MEM_SIZE - sizeof(dmd_ent_t)]; 80 | e->header.d_size = DM_MEM_SIZE - sizeof(dmd_ent_t); 81 | e->header.used = 0; 82 | e->data_p = &work_mem[0]; 83 | 84 | master_e = e; 85 | last_e = e; 86 | } 87 | 88 | /** 89 | * Allocate a memory dynamically 90 | * @param size size of the memory to allocate in bytes 91 | * @return pointer to the allocated memory 92 | * !!!IMPORTANT!!! it is special pointer, see the file header for more information 93 | */ 94 | void * dmd_alloc(uint32_t size) 95 | { 96 | if(size == 0) { 97 | return &zero_mem; 98 | } 99 | 100 | /*Round the size up to 4*/ 101 | if(size & 0x3 ) { 102 | size = size & (~0x3); 103 | size += 4; 104 | } 105 | 106 | void * alloc = NULL; 107 | alloc = ent_alloc(master_e, size); 108 | return alloc; 109 | } 110 | 111 | /** 112 | * Free an allocated data 113 | * @param data pointer to an allocated memory 114 | * (without da() tag, see file header for more information) 115 | */ 116 | void dmd_free(void * data) 117 | { 118 | if(data == &zero_mem) return; 119 | if(data == NULL) return; 120 | 121 | /*Mark the entry as free*/ 122 | dmd_ent_t * free_e = data; 123 | free_e->header.used = 0; 124 | 125 | /*Join this free area into the master_e. 126 | To achieve this move all data after p forward with p->header.d_size spaces. 127 | Hence p->data will shifted directly before master_e->data_p */ 128 | dmd_ent_t * next_e; 129 | uint32_t i; 130 | 131 | /*Pre-load the next_e*/ 132 | next_e = ent_get_next_ord(free_e); 133 | /*Iterate through all entries after act_e until reach master_e*/ 134 | while(next_e != master_e) { 135 | /* Swap the data of entries and their data_p */ 136 | for(i = 0; i < next_e->header.d_size; i++) { 137 | free_e->data_p[i] = next_e->data_p[i]; 138 | } 139 | 140 | next_e->data_p = free_e->data_p; /*Put the next on the free*/ 141 | free_e->data_p = &next_e->data_p[next_e->header.d_size]; /*Put the free after the next*/ 142 | 143 | /* Get the next e in order*/ 144 | next_e = ent_get_next_ord(free_e); 145 | } 146 | 147 | /*Join free_e with master_e*/ 148 | master_e->header.d_size += free_e->header.d_size; 149 | master_e->data_p = free_e->data_p; 150 | 151 | /*Mark the entry position as free*/ 152 | memset(free_e->data_p, 0, free_e->header.d_size); 153 | free_e->data_p = NULL; 154 | free_e->header.d_size = 0; 155 | 156 | /* Increment last_e if it was freed and increase master_e size*/ 157 | if(free_e == last_e) { 158 | do { 159 | master_e->header.d_size += sizeof(dmd_ent_t); 160 | last_e ++; 161 | }while(last_e->data_p == NULL); 162 | 163 | } 164 | } 165 | 166 | /** 167 | * Reallocate a memory with a the size. The old content will be kept. 168 | * @param data pointer to an allocated memory. (without da() tag see file header for more information) 169 | * Its content will be copied to the new memory block and freed 170 | * @param new_size the desires new size in byte 171 | * @return pointer to the new memory 172 | * !!!IMPORTANT!!! it is special pointer, see the file header for more information 173 | 174 | */ 175 | void * dmd_realloc(void * data_p, uint32_t new_size) 176 | { 177 | uint8_t dp * new_p; 178 | 179 | new_p = dmd_alloc(new_size); 180 | 181 | if(new_p != NULL && data_p != NULL) { 182 | /*Copy the old data to the new. Use the smaller size*/ 183 | uint32_t old_size = dmd_get_size(data_p); 184 | if(old_size != 0) { 185 | memcpy(da(new_p), da(((uint8_t dp *)data_p)), min(new_size, old_size)); 186 | dmd_free(data_p); 187 | } 188 | } 189 | 190 | return new_p; 191 | } 192 | 193 | 194 | /** 195 | * Give information about the work memory of dynamic allocation 196 | * @param mon_p pointer to a mon_p variable, the result of the analysis will be stored here 197 | */ 198 | void dmd_monitor(dmd_mon_t * mon_p) 199 | { 200 | //Init the data 201 | memset(mon_p, 0, sizeof(dmd_mon_t)); 202 | 203 | dmd_ent_t * e; 204 | e = NULL; 205 | 206 | e = ent_get_next(e); 207 | 208 | while(e != NULL) { 209 | if(e->header.used == 0) { 210 | mon_p->cnt_free++; 211 | mon_p->size_free += e->header.d_size; 212 | if(e->header.d_size > mon_p->size_free_big) { 213 | mon_p->size_free_big = e->header.d_size; 214 | } 215 | } else { 216 | mon_p->cnt_used++; 217 | } 218 | 219 | e = ent_get_next(e); 220 | } 221 | 222 | mon_p->pct_frag = (uint32_t)mon_p->size_free_big * 100U / mon_p->size_free; 223 | mon_p->pct_frag = 100 - mon_p->pct_frag; 224 | } 225 | 226 | /** 227 | * Give the size a allocated memory 228 | * @param data pointer to an allocated memory (without da() tag see file header for more information ) 229 | * @return the size of data memory in bytes 230 | */ 231 | uint32_t dmd_get_size(void * data) 232 | { 233 | if(data == &zero_mem) return 0; 234 | 235 | dmd_ent_t * e = data; /*p is entry*/ 236 | return e->header.d_size; 237 | 238 | } 239 | /********************** 240 | * STATIC FUNCTIONS 241 | **********************/ 242 | 243 | /** 244 | * Give the next entry after 'act_e' 245 | * @param act_e pointer to an entry 246 | * @return pointer to an entry after 'act_e' 247 | */ 248 | static dmd_ent_t * ent_get_next(dmd_ent_t * act_e) 249 | { 250 | dmd_ent_t * next_e = NULL; 251 | 252 | if(act_e == NULL) { 253 | next_e = master_e; 254 | } else { 255 | next_e = act_e - 1; 256 | 257 | if(next_e < last_e) { 258 | next_e = NULL; 259 | } 260 | } 261 | 262 | return next_e; 263 | } 264 | 265 | /** 266 | * With DM_POL_DEFRAG the order of entries not same like the order of allocated memories. 267 | * This function gives the next entry in the order of allocated memories 268 | * @param e pointer to an entry 269 | * @return pointer to an entry which data begins after the data of 'e' 270 | */ 271 | static dmd_ent_t * ent_get_next_ord(dmd_ent_t * e) 272 | { 273 | dmd_ent_t * next_e; 274 | 275 | uint8_t * next_data_p = &e->data_p[e->header.d_size]; 276 | 277 | for(next_e = last_e; next_e < master_e; next_e++) { 278 | if(next_e->data_p == next_data_p) { 279 | break; 280 | } 281 | } 282 | 283 | return next_e; 284 | } 285 | 286 | 287 | /** 288 | * Try to do the real allocation with a given size 289 | * @param e try to allocate to this entry 290 | * @param size size of the new memory in bytes 291 | * @return pointer to the allocated memory or NULL if not enough memory in the entry 292 | */ 293 | static void * ent_alloc(dmd_ent_t * e, uint32_t size) 294 | { 295 | void * alloc = NULL; 296 | 297 | /* Always allocate to the master_e (e == master_e) */ 298 | 299 | /* In master_e has to remain at leat 2 entry space: 300 | * 1 entry space to ensure space for new allocation and 301 | * an other to be sure master_e size will not be 0 */ 302 | if(e->header.d_size >= size + 2 * sizeof(dmd_ent_t)) 303 | { 304 | alloc = ent_trunc(e, size); 305 | } 306 | 307 | return alloc; 308 | } 309 | 310 | /** 311 | * Truncate the data of entry to the given size 312 | * @param e Pointer to an entry 313 | * @param size new size in bytes 314 | * @return the new entry created from the remaining memory 315 | */ 316 | static dmd_ent_t * ent_trunc(dmd_ent_t * e, uint32_t size) 317 | { 318 | dmd_ent_t * new_e; 319 | 320 | /*Search place for a new entry at the end of the memory*/ 321 | for(new_e = master_e; new_e >= last_e; new_e--) { 322 | /*Free entry found before last_e*/ 323 | if(new_e->data_p == NULL) { 324 | break; 325 | } 326 | } 327 | 328 | if(new_e < last_e) { 329 | /*New entry is allocated so master entry become smaller*/ 330 | master_e->header.d_size -= sizeof(dmd_ent_t); 331 | last_e --; 332 | } 333 | 334 | /*Set the parameters in the new last_e*/ 335 | new_e->header.d_size = size; 336 | new_e->header.used = 1; 337 | new_e->data_p = master_e->data_p; 338 | 339 | /*Update master_e*/ 340 | master_e->data_p = master_e->data_p + size; 341 | master_e->header.d_size -= size; 342 | 343 | return new_e; 344 | } 345 | 346 | #endif 347 | -------------------------------------------------------------------------------- /mem/dyn_mem_defr.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file dyn_mem.h 3 | * 4 | */ 5 | 6 | #ifndef DYN_MEM_H 7 | #define DYN_MEM_H 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | 14 | /********************* 15 | * INCLUDES 16 | *********************/ 17 | #include "../../misc_conf.h" 18 | 19 | #if USE_DYN_MEM_DEFR != 0 20 | 21 | #include 22 | #include 23 | 24 | /********************* 25 | * DEFINES 26 | *********************/ 27 | 28 | /********************** 29 | * TYPEDEFS 30 | **********************/ 31 | 32 | /*The size of this union must be 4 bytes (uint32_t)*/ 33 | typedef union 34 | { 35 | struct 36 | { 37 | uint32_t used:1; //1: if the entry is used 38 | uint32_t d_size:31; //Size off the data (1 means 4 bytes) 39 | }; 40 | uint32_t header; //The header (used + d_size) 41 | }dmd_headr_t; 42 | 43 | typedef struct 44 | { 45 | uint8_t * data_p; 46 | 47 | dmd_headr_t header; 48 | 49 | }dmd_ent_t; 50 | 51 | typedef struct 52 | { 53 | uint32_t cnt_free; 54 | uint32_t cnt_used; 55 | uint32_t size_free; 56 | uint32_t size_free_big; 57 | uint32_t pct_frag; 58 | }dmd_mon_t; 59 | 60 | 61 | /********************** 62 | * GLOBAL PROTOTYPES 63 | **********************/ 64 | 65 | /** 66 | * Initiaize the dyn_mem module (work memory and other variables) 67 | */ 68 | void dmd_init(void); 69 | 70 | /** 71 | * Allocate a memory dynamically 72 | * @param size size of the memory to allocate in bytes 73 | * @return pointer to the allocated memory 74 | * !!!IMPORTANT!!! it is special pointer, see the file header for more information 75 | */ 76 | void * dmd_alloc(uint32_t size); 77 | 78 | /** 79 | * Free an allocated data 80 | * @param data pointer to an allocated memory 81 | * (without da() tag, see file header for more information) 82 | */ 83 | void dmd_free(void * data); 84 | 85 | /** 86 | * Give information about the work memory of dynamic allocation 87 | * @param mon_p pointer to a mon_p variable, the result of the analysis will be stored here 88 | */ 89 | void dmd_monitor(dmd_mon_t * mon_p); 90 | 91 | /** 92 | * Give the size a allocated memory 93 | * @param data pointer to an allocated memory (without da() tag see file header for more information ) 94 | * @return the size of data memory in bytes 95 | */ 96 | uint32_t dmd_get_size(void * data); 97 | 98 | /********************** 99 | * MACROS 100 | **********************/ 101 | 102 | #define da(p) (*p) 103 | #define dp * 104 | 105 | 106 | #endif /*USE_DYN_MEM*/ 107 | 108 | #ifdef __cplusplus 109 | } /* extern "C" */ 110 | #endif 111 | 112 | #endif 113 | 114 | -------------------------------------------------------------------------------- /mem/fifo.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file fifo.c 3 | * Classical First In First Out buffer implementation 4 | */ 5 | 6 | /********************* 7 | * INCLUDES 8 | *********************/ 9 | #include "../../misc_conf.h" 10 | #if USE_FIFO != 0 11 | 12 | #include "fifo.h" 13 | #include 14 | #include 15 | 16 | /********************* 17 | * DEFINES 18 | *********************/ 19 | 20 | /********************** 21 | * TYPEDEFS 22 | **********************/ 23 | 24 | /********************** 25 | * STATIC PROTOTYPES 26 | **********************/ 27 | 28 | /********************** 29 | * STATIC VARIABLES 30 | **********************/ 31 | 32 | /********************** 33 | * MACROS 34 | **********************/ 35 | 36 | /********************** 37 | * GLOBAL FUNCTIONS 38 | **********************/ 39 | 40 | /** 41 | * Initialize a fifo. 42 | * @param fifo_p pointer to a fifo_t variable 43 | * @param buf_p pointer to the buffer of the fifo (item_size * item_num bytes size ) 44 | * @param item_size the of an item stored by the fifo (in bytes) 45 | * @param item_num number of elements stored by the fifo 46 | */ 47 | void fifo_init(fifo_t * fifo_p, void * buf_p, uint32_t item_size, uint32_t item_num) 48 | { 49 | fifo_p->buf = buf_p; 50 | fifo_p->item_num = item_num; 51 | fifo_p->item_size = item_size; 52 | fifo_p->rp = 0; 53 | fifo_p->wp = 0; 54 | fifo_p->empty = 1; 55 | fifo_p->full = 0; 56 | } 57 | 58 | /** 59 | * Add item to the fifo 60 | * @param fifo_p pointer to fifo_t variable 61 | * @param data_p pointer to a data to add 62 | * @return true: if the data is pushed, false: if the fifo was full 63 | */ 64 | bool fifo_push(fifo_t * fifo_p, const void * data_p) 65 | { 66 | if(fifo_p->full != 0) return false; 67 | 68 | /* Copy data into the fifo */ 69 | uint8_t * wr_begin = fifo_p->buf; 70 | wr_begin += (uint32_t) fifo_p->wp * fifo_p->item_size; 71 | memcpy(wr_begin, data_p, fifo_p->item_size); 72 | 73 | /*Increase the write pointer*/ 74 | fifo_p->wp ++; 75 | 76 | if(fifo_p->wp >= fifo_p->item_num) fifo_p->wp = 0; 77 | 78 | /*Set the fifo full if necessary*/ 79 | if(fifo_p->rp == fifo_p->wp) fifo_p->full = 1; 80 | 81 | /*The fifo surely will not be empty after that*/ 82 | fifo_p->empty = 0; 83 | 84 | return true; 85 | } 86 | 87 | /** 88 | * Add multiple data to the fifo 89 | * @param fifo_p pointer to a fifo_t variable 90 | * @param data_p pointer to the data to push 91 | * @param num number of items to push 92 | * @return number of pushed items (<= 'num') 93 | */ 94 | uint32_t fifo_push_mult(fifo_t * fifo_p, const void * data_p, uint32_t num) 95 | { 96 | uint32_t push_num = 0; 97 | const uint8_t * data_u8_p = data_p; 98 | uint8_t suc; 99 | 100 | for(push_num = 0; push_num < num; push_num ++) { 101 | /* Push data*/ 102 | suc = fifo_push(fifo_p, data_u8_p); 103 | 104 | /* Check the result and break on fail*/ 105 | if(suc == 0) { 106 | break; 107 | } else { 108 | data_u8_p += fifo_p->item_size; 109 | } 110 | } 111 | 112 | return push_num; 113 | } 114 | 115 | /** 116 | * Read data from a fifo 117 | * @param fifo_p pointer to a fifo_t variable 118 | * @param data_p pointer to buffer to store the read data 119 | * @return true: if the data is popped, false: if the fifo was empty 120 | */ 121 | bool fifo_pop(fifo_t * fifo_p, void * data_p) 122 | { 123 | if(fifo_p->empty != 0) return false; 124 | 125 | /* Copy data into the fifo */ 126 | uint8_t * rd_begin = fifo_p->buf; 127 | rd_begin += (uint32_t)fifo_p->rp * fifo_p->item_size; 128 | memcpy(data_p, rd_begin, fifo_p->item_size); 129 | 130 | /*Increase the read pointer*/ 131 | fifo_p->rp ++; 132 | 133 | if(fifo_p->rp >= fifo_p->item_num) fifo_p->rp = 0; 134 | 135 | /*Set the fifo empty if necessary*/ 136 | if(fifo_p->rp == fifo_p->wp) fifo_p->empty = 1; 137 | 138 | /*The fifo surely will not be full after that*/ 139 | fifo_p->full = 0; 140 | 141 | return true; 142 | } 143 | /** 144 | * Read multiple data from a fifo 145 | * @param fifo_p pointer to fifo_t variable 146 | * @param data_p buffer to store the read data 147 | * @param num number of items to read 148 | * @return number of popped items (<= 'num') 149 | */ 150 | uint32_t fifo_pop_mult(fifo_t * fifo_p, void * data_p, uint32_t num) 151 | { 152 | uint32_t pop_num = 0; 153 | uint8_t * data_u8_p = data_p; 154 | uint8_t suc; 155 | 156 | for(pop_num = 0; pop_num < num; pop_num ++) { 157 | /* Pop data*/ 158 | suc = fifo_pop(fifo_p, data_u8_p); 159 | 160 | /* Check the result and break on fail*/ 161 | if(suc == 0) { 162 | break; 163 | } 164 | else { 165 | data_u8_p += fifo_p->item_size; 166 | } 167 | } 168 | 169 | return pop_num; 170 | } 171 | 172 | /** 173 | * Make the fifo empty 174 | * @param fifo_p pointer to a fifo_t variable 175 | */ 176 | void fifo_clear(fifo_t * fifo_p) 177 | { 178 | fifo_p->rp = 0; 179 | fifo_p->wp = 0; 180 | fifo_p->empty = 1; 181 | fifo_p->full = 0; 182 | } 183 | 184 | /** 185 | * Returns with the number of free spaces in the fifo (max. 'item_num') 186 | * @param fifo_p pointer to a fifo_t variable 187 | * @return Free spaces is the fifo. (0 means the fifo is full) 188 | */ 189 | uint32_t fifo_get_free(fifo_t * fifo_p) 190 | { 191 | uint32_t free_num; 192 | 193 | if(fifo_p->rp > fifo_p->wp) { 194 | free_num = fifo_p->rp - fifo_p->wp; 195 | } else if (fifo_p->rp < fifo_p->wp) { 196 | free_num = fifo_p->item_num - 197 | (fifo_p->wp - fifo_p->rp); 198 | } else { 199 | if(fifo_p->empty != 0) { 200 | free_num = fifo_p->item_num; 201 | } else { 202 | free_num = 0; 203 | } 204 | } 205 | 206 | return free_num; 207 | } 208 | 209 | /********************** 210 | * STATIC FUNCTIONS 211 | **********************/ 212 | 213 | #endif 214 | -------------------------------------------------------------------------------- /mem/fifo.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file fifo.h 3 | * Classical First In First Out buffer implementation 4 | */ 5 | 6 | #ifndef FIFO_H 7 | #define FIFO_H 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | 14 | /********************* 15 | * INCLUDES 16 | *********************/ 17 | #include "../../misc_conf.h" 18 | 19 | #if USE_FIFO != 0 20 | #include 21 | #include 22 | #include 23 | #include "dyn_mem.h" 24 | 25 | /********************* 26 | * DEFINES 27 | *********************/ 28 | 29 | /********************** 30 | * TYPEDEFS 31 | **********************/ 32 | 33 | /** 34 | * Descriptor of a fifo 35 | */ 36 | typedef struct 37 | { 38 | uint32_t item_size; 39 | uint32_t item_num; 40 | uint32_t wp; 41 | uint32_t rp; 42 | uint8_t empty :1; 43 | uint8_t full :1; 44 | uint8_t * buf; 45 | }fifo_t; 46 | 47 | /********************** 48 | * GLOBAL PROTOTYPES 49 | **********************/ 50 | 51 | /** 52 | * Initialize a fifo. 53 | * @param fifo_p pointer to a fifo_t variable 54 | * @param buf_p pointer to the buffer of the fifo (item_size * item_num bytes size ) 55 | * @param item_size the of an item stored by the fifo (in bytes) 56 | * @param item_num number of elements stored by the fifo 57 | */ 58 | void fifo_init(fifo_t * fifo_p, void * buf_p, uint32_t item_size, uint32_t item_num); 59 | 60 | /** 61 | * Add item to the fifo 62 | * @param fifo_p pointer to fifo_t variable 63 | * @param data_p pointer to a data to add 64 | * @return true: if the data is pushed, false: if the fifo was full 65 | */ 66 | bool fifo_push(fifo_t * fifo_p, const void * data_p); 67 | 68 | /** 69 | * Add multiple data to the fifo 70 | * @param fifo_p pointer to a fifo_t variable 71 | * @param data_p pointer to the data to push 72 | * @param num number of items to push 73 | * @return number of pushed items (<= 'num') 74 | */ 75 | uint32_t fifo_push_mult(fifo_t * fifo_p, const void * data_p, uint32_t num); 76 | 77 | /** 78 | * Read data from a fifo 79 | * @param fifo_p pointer to a fifo_t variable 80 | * @param data_p pointer to buffer to store the read data 81 | * @return true: if the data is popped, false: if the fifo was empty 82 | */ 83 | bool fifo_pop(fifo_t * fifo_p, void * data_p); 84 | 85 | /** 86 | * Read multiple data from a fifo 87 | * @param fifo_p pointer to fifo_t variable 88 | * @param data_p buffer to store the read data 89 | * @param num number of items to read 90 | * @return number of popped items (<= 'num') 91 | */ 92 | uint32_t fifo_pop_mult(fifo_t * fifo_p, void * data_p, uint32_t num); 93 | 94 | /** 95 | * Make the fifo empty 96 | * @param fifo_p pointer to a fifo_t variable 97 | */ 98 | void fifo_clear(fifo_t * fifo_p); 99 | 100 | /** 101 | * Returns with the number of free spaces in the fifo (max. 'item_num') 102 | * @param fifo_p pointer to a fifo_t variable 103 | * @return Free spaces is the fifo. (0 means the fifo is full) 104 | */ 105 | uint32_t fifo_get_free(fifo_t * fifo_p); 106 | 107 | /********************** 108 | * MACROS 109 | **********************/ 110 | 111 | #endif /*USE_FIFO*/ 112 | 113 | #ifdef __cplusplus 114 | } /* extern "C" */ 115 | #endif 116 | 117 | #endif 118 | -------------------------------------------------------------------------------- /mem/linked_list.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file linked_list.c 3 | * Handle linked lists. 4 | * The nodes are dynamically allocated by the dyn_mem module, 5 | */ 6 | 7 | /********************* 8 | * INCLUDES 9 | *********************/ 10 | #include "../../misc_conf.h" 11 | #if USE_LINKED_LIST != 0 12 | 13 | #include 14 | #include 15 | 16 | #include "linked_list.h" 17 | #include "dyn_mem.h" 18 | 19 | /********************* 20 | * DEFINES 21 | *********************/ 22 | #define LL_NODE_META_SIZE (sizeof(ll_node_t*) + sizeof(ll_node_t*)) 23 | #define LL_PREV_P_OFFSET(ll_p) (ll_p->n_size) 24 | #define LL_NEXT_P_OFFSET(ll_p) (ll_p->n_size + sizeof(ll_node_t*)) 25 | /********************** 26 | * TYPEDEFS 27 | **********************/ 28 | 29 | /********************** 30 | * STATIC PROTOTYPES 31 | **********************/ 32 | static void node_set_prev(ll_dsc_t * ll_p, ll_node_t* act, ll_node_t* prev); 33 | static void node_set_next(ll_dsc_t * ll_p, ll_node_t* act, ll_node_t* next); 34 | 35 | /********************** 36 | * STATIC VARIABLES 37 | **********************/ 38 | 39 | /********************** 40 | * MACROS 41 | **********************/ 42 | 43 | /********************** 44 | * GLOBAL FUNCTIONS 45 | **********************/ 46 | 47 | /** 48 | * Initialize linked list 49 | * @param ll_dsc pointer to ll_dsc variable 50 | * @param n_size the size of 1 node in bytes 51 | */ 52 | void ll_init(ll_dsc_t * ll_p, uint32_t n_size) 53 | { 54 | ll_p->head = NULL; 55 | ll_p->tail = NULL; 56 | 57 | if(n_size & 0b11) { 58 | n_size &= ~0b11; 59 | n_size += 4; 60 | } 61 | 62 | ll_p->n_size = n_size; 63 | } 64 | 65 | /** 66 | * Add a new head to a linked list 67 | * @param ll_p pointer to linked list 68 | * @return pointer to the new head 69 | */ 70 | void * ll_ins_head(ll_dsc_t * ll_p) 71 | { 72 | ll_node_t* n_new; 73 | 74 | n_new = dm_alloc(ll_p->n_size + LL_NODE_META_SIZE); 75 | 76 | if(n_new != NULL) { 77 | node_set_prev(ll_p, n_new, NULL); /*No prev. before the new head*/ 78 | node_set_next(ll_p, n_new, ll_p->head); /*After new comes the old head*/ 79 | 80 | if(ll_p->head != NULL) { /*If there is old head then before it goes the new*/ 81 | node_set_prev(ll_p, ll_p->head, n_new); 82 | } 83 | 84 | ll_p->head = n_new; /*Set the new head in the dsc.*/ 85 | if(ll_p->tail == NULL) {/*If there is no tail (1. node) set the tail too*/ 86 | ll_p->tail = n_new; 87 | } 88 | } 89 | 90 | return n_new; 91 | } 92 | 93 | /** 94 | * Add a new tail to a linked list 95 | * @param ll_p pointer to linked list 96 | * @return pointer to the new tail 97 | */ 98 | void * ll_ins_tail(ll_dsc_t * ll_p) 99 | { 100 | ll_node_t* n_new; 101 | 102 | n_new = dm_alloc(ll_p->n_size + LL_NODE_META_SIZE); 103 | 104 | if(n_new != NULL) { 105 | node_set_next(ll_p, n_new, NULL); /*No next after the new tail*/ 106 | node_set_prev(ll_p, n_new, ll_p->tail); /*The prev. before new is tho old tail*/ 107 | if(ll_p->tail != NULL) { /*If there is old tail then the new comes after it*/ 108 | node_set_next(ll_p, ll_p->tail, n_new); 109 | } 110 | 111 | ll_p->tail = n_new; /*Set the new tail in the dsc.*/ 112 | if(ll_p->head == NULL) { /*If there is no head (1. node) set the head too*/ 113 | ll_p->head = n_new; 114 | } 115 | } 116 | 117 | return n_new; 118 | } 119 | 120 | 121 | /** 122 | * Remove the node 'node_p' from 'll_p' linked list. 123 | * It Dose not free the the memory of node. 124 | * @param ll_p pointer to the linked list of 'node_p' 125 | * @param node_p pointer to node in 'll_p' linked list 126 | */ 127 | void ll_rem(ll_dsc_t * ll_p, void * node_p) 128 | { 129 | if(ll_get_head(ll_p) == node_p) { 130 | /*The new head will be the node after 'n_act'*/ 131 | ll_p->head = ll_get_next(ll_p, node_p); 132 | if(ll_p->head == NULL) { 133 | ll_p->tail = NULL; 134 | } 135 | else { 136 | node_set_prev(ll_p, ll_p->head, NULL); 137 | } 138 | } 139 | else if(ll_get_tail(ll_p) == node_p) { 140 | /*The new tail will be the node before 'n_act'*/ 141 | ll_p->tail = ll_get_prev(ll_p, node_p); 142 | if(ll_p->tail == NULL) { 143 | ll_p->head = NULL; 144 | } 145 | else { 146 | node_set_next(ll_p, ll_p->tail, NULL); 147 | } 148 | } 149 | else 150 | { 151 | ll_node_t* n_prev = ll_get_prev(ll_p, node_p); 152 | ll_node_t* n_next = ll_get_next(ll_p, node_p); 153 | 154 | node_set_next(ll_p, n_prev, n_next); 155 | node_set_prev(ll_p, n_next, n_prev); 156 | } 157 | } 158 | 159 | /** 160 | * Remove and free all elements from a linked list. 161 | * @param ll_p pointer to linked list 162 | */ 163 | void ll_clear(ll_dsc_t * ll_p) 164 | { 165 | void * i; 166 | void * i_next; 167 | 168 | i = ll_get_head(ll_p); 169 | i_next = NULL; 170 | 171 | while(i != NULL) { 172 | i_next = ll_get_next(ll_p, i); 173 | 174 | ll_rem(ll_p, i); 175 | dm_free(i); 176 | 177 | i = i_next; 178 | } 179 | } 180 | 181 | /** 182 | * Move a node to a new linked list 183 | * @param ll_ori_p pointer to the original (old) linked list 184 | * @param ll_new_p pointer to the new linked list 185 | * @param node pointer to a node 186 | */ 187 | void ll_chg_list(ll_dsc_t * ll_ori_p, ll_dsc_t * ll_new_p, void * node) 188 | { 189 | ll_rem(ll_ori_p, node); 190 | 191 | /*Set node as head*/ 192 | node_set_prev(ll_new_p, node, NULL); 193 | node_set_next(ll_new_p, node, ll_new_p->head); 194 | 195 | if(ll_new_p->head != NULL) { /*If there is old head then before it goes the new*/ 196 | node_set_prev(ll_new_p, ll_new_p->head, node); 197 | } 198 | 199 | ll_new_p->head = node; /*Set the new head in the dsc.*/ 200 | if(ll_new_p->tail == NULL) { /*If there is no tail (first node) set the tail too*/ 201 | ll_new_p->tail = node; 202 | } 203 | } 204 | 205 | /** 206 | * Return with head node of the linked list 207 | * @param ll_p pointer to linked list 208 | * @return pointer to the head of 'll_p' 209 | */ 210 | void * ll_get_head(ll_dsc_t * ll_p) 211 | { 212 | void * head = NULL; 213 | 214 | if(ll_p != NULL) { 215 | head = ll_p->head; 216 | } 217 | 218 | return head; 219 | } 220 | 221 | /** 222 | * Return with tail node of the linked list 223 | * @param ll_p pointer to linked list 224 | * @return pointer to the head of 'll_p' 225 | */ 226 | void * ll_get_tail(ll_dsc_t * ll_p) 227 | { 228 | void * tail = NULL; 229 | 230 | if(ll_p != NULL) { 231 | tail = ll_p->tail; 232 | } 233 | 234 | return tail; 235 | } 236 | 237 | /** 238 | * Return with the pointer of the next node after 'n_act' 239 | * @param ll_p pointer to linked list 240 | * @param n_act pointer a node 241 | * @return pointer to the next node 242 | */ 243 | void * ll_get_next(ll_dsc_t * ll_p, void * n_act) 244 | { 245 | void * next = NULL; 246 | 247 | if(ll_p != NULL) { 248 | ll_node_t* n_act_d = n_act; 249 | memcpy(&next, n_act_d + LL_NEXT_P_OFFSET(ll_p), sizeof(void *)); 250 | } 251 | 252 | return next; 253 | } 254 | 255 | /** 256 | * Return with the pointer of the previous node after 'n_act' 257 | * @param ll_p pointer to linked list 258 | * @param n_act pointer a node 259 | * @return pointer to the previous node 260 | */ 261 | void * ll_get_prev(ll_dsc_t * ll_p, void * n_act) 262 | { 263 | void * prev = NULL; 264 | 265 | if(ll_p != NULL) { 266 | ll_node_t* n_act_d = n_act; 267 | memcpy(&prev, n_act_d + LL_PREV_P_OFFSET(ll_p), sizeof(void *)); 268 | } 269 | 270 | return prev; 271 | } 272 | 273 | void ll_swap(ll_dsc_t * ll_p, void * n1_p, void * n2_p) 274 | { 275 | 276 | } 277 | 278 | /********************** 279 | * STATIC FUNCTIONS 280 | **********************/ 281 | 282 | /** 283 | * Set the 'pervious node pointer' of a node 284 | * @param ll_p pointer to linked list 285 | * @param act pointer to a node which prev. node pointer should be set 286 | * @param prev pointer to a node which should be the previous node before 'act' 287 | */ 288 | static void node_set_prev(ll_dsc_t * ll_p, ll_node_t* act, ll_node_t* prev) 289 | { 290 | memcpy(act + LL_PREV_P_OFFSET(ll_p), &prev, sizeof(ll_node_t*)); 291 | } 292 | 293 | /** 294 | * Set the 'next node pointer' of a node 295 | * @param ll_p pointer to linked list 296 | * @param act pointer to a node which next node pointer should be set 297 | * @param next pointer to a node which should be the next node before 'act' 298 | */ 299 | static void node_set_next(ll_dsc_t * ll_p, ll_node_t* act, ll_node_t* next) 300 | { 301 | memcpy(act + LL_NEXT_P_OFFSET(ll_p), &next, sizeof(ll_node_t*)); 302 | } 303 | 304 | #endif 305 | -------------------------------------------------------------------------------- /mem/linked_list.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file linked_list.c 3 | * Handle linked lists. The nodes are dynamically allocated by the dyn_mem module. 4 | */ 5 | 6 | #ifndef LINKED_LIST_H 7 | #define LINKED_LIST_H 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | 14 | /********************* 15 | * INCLUDES 16 | *********************/ 17 | #include "../../misc_conf.h" 18 | 19 | #if USE_LINKED_LIST != 0 20 | #include "dyn_mem.h" 21 | #include 22 | #include 23 | 24 | /********************* 25 | * DEFINES 26 | *********************/ 27 | 28 | /********************** 29 | * TYPEDEFS 30 | **********************/ 31 | 32 | /*Dummy type to make handling easier*/ 33 | typedef uint8_t ll_node_t; 34 | 35 | /*Description of a linked list*/ 36 | typedef struct 37 | { 38 | uint32_t n_size; 39 | ll_node_t* head; 40 | ll_node_t* tail; 41 | }ll_dsc_t; 42 | 43 | /********************** 44 | * GLOBAL PROTOTYPES 45 | **********************/ 46 | 47 | /** 48 | * Initialize linked list 49 | * @param ll_dsc pointer to ll_dsc variable 50 | * @param n_size the size of 1 node in bytes 51 | */ 52 | void ll_init(ll_dsc_t * ll_p, uint32_t n_size); 53 | 54 | /** 55 | * Add a new head to a linked list 56 | * @param ll_p pointer to linked list 57 | * @return pointer to the new head 58 | */ 59 | void * ll_ins_head(ll_dsc_t * ll_p); 60 | 61 | /** 62 | * Add a new tail to a linked list 63 | * @param ll_p pointer to linked list 64 | * @return pointer to the new tail 65 | */ 66 | void * ll_ins_tail(ll_dsc_t * ll_p); 67 | 68 | /** 69 | * Remove the node 'node_p' from 'll_p' linked list. 70 | * It Dose not free the the memory of node. 71 | * @param ll_p pointer to the linked list of 'node_p' 72 | * @param node_p pointer to node in 'll_p' linked list 73 | */ 74 | void ll_rem(ll_dsc_t * ll_p, void * node_p); 75 | 76 | /** 77 | * Remove and free all elements from a linked list. 78 | * @param ll_p pointer to linked list 79 | */ 80 | void ll_clear(ll_dsc_t * ll_p); 81 | 82 | /** 83 | * Move a node to a new linked list 84 | * @param ll_ori_p pointer to the original (old) linked list 85 | * @param ll_new_p pointer to the new linked list 86 | * @param node pointer to a node 87 | */ 88 | void ll_chg_list(ll_dsc_t * ll_ori_p, ll_dsc_t * ll_new_p, void * node); 89 | 90 | /** 91 | * Return with head node of the linked list 92 | * @param ll_p pointer to linked list 93 | * @return pointer to the head of 'll_p' 94 | */ 95 | void * ll_get_head(ll_dsc_t * ll_p); 96 | 97 | /** 98 | * Return with tail node of the linked list 99 | * @param ll_p pointer to linked list 100 | * @return pointer to the head of 'll_p' 101 | */ 102 | void * ll_get_tail(ll_dsc_t * ll_p); 103 | 104 | /** 105 | * Return with the pointer of the next node after 'n_act' 106 | * @param ll_p pointer to linked list 107 | * @param n_act pointer a node 108 | * @return pointer to the next node 109 | */ 110 | void * ll_get_next(ll_dsc_t * ll_p, void * n_act); 111 | 112 | /** 113 | * Return with the pointer of the previous node after 'n_act' 114 | * @param ll_p pointer to linked list 115 | * @param n_act pointer a node 116 | * @return pointer to the previous node 117 | */ 118 | void * ll_get_prev(ll_dsc_t * ll_p, void * n_act); 119 | 120 | /********************** 121 | * MACROS 122 | **********************/ 123 | 124 | #define LL_READ(list, i) for(i = ll_get_head(&list); i != NULL; i = ll_get_next(&list, i)) 125 | 126 | #define LL_READ_BACK(list, i) for(i = ll_get_tail(&list); i != NULL; i = ll_get_prev(&list, i)) 127 | 128 | #endif /*USE_LINKED_LIST*/ 129 | 130 | #ifdef __cplusplus 131 | } /* extern "C" */ 132 | #endif 133 | 134 | #endif 135 | -------------------------------------------------------------------------------- /misc.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file misc.c 3 | * 4 | */ 5 | 6 | /********************* 7 | * INCLUDES 8 | *********************/ 9 | #include "../misc_conf.h" 10 | 11 | #include "os/idle.h" 12 | #include "mem/dyn_mem.h" 13 | #include "os/ptask.h" 14 | #include "fs/fsint.h" 15 | #include "fs/ufs/ufs.h" 16 | #include "fs/fat32/fat32.h" 17 | #include "fs/linuxfs/linuxfs.h" 18 | #include "gfx/font.h" 19 | #include "gfx/anim.h" 20 | #include "comm/wifimng.h" 21 | #include "comm/gsmmng.h" 22 | 23 | /********************* 24 | * DEFINES 25 | *********************/ 26 | 27 | /********************** 28 | * TYPEDEFS 29 | **********************/ 30 | 31 | /********************** 32 | * STATIC PROTOTYPES 33 | **********************/ 34 | 35 | /********************** 36 | * STATIC VARIABLES 37 | **********************/ 38 | 39 | /********************** 40 | * MACROS 41 | **********************/ 42 | 43 | /********************** 44 | * GLOBAL FUNCTIONS 45 | **********************/ 46 | 47 | /** 48 | * Initialize the enabled misc. modules 49 | */ 50 | void misc_init(void) 51 | { 52 | 53 | #if USE_IDLE != 0 54 | idle_init(); /*Init. it as soon as possible*/ 55 | #endif 56 | 57 | #if USE_DYN_MEM != 0 58 | dm_init(); 59 | #endif 60 | 61 | #if USE_PTASK != 0 62 | ptask_init(); 63 | #endif 64 | 65 | #if USE_FSINT != 0 /*Init is befor other FS inits*/ 66 | fs_init(); 67 | #endif 68 | 69 | #if USE_UFS != 0 70 | ufs_init(); 71 | #endif 72 | 73 | #if USE_FAT32 != 0 74 | fat32_init(); 75 | #endif 76 | 77 | #if USE_LINUXFS != 0 78 | linuxfs_init(); 79 | #endif 80 | 81 | #if USE_FONT != 0 82 | font_init(); 83 | #endif 84 | 85 | #if USE_ANIM != 0 86 | anim_init(); 87 | #endif 88 | 89 | #if USE_WIFIMNG != 0 90 | wifimng_init(); 91 | #endif 92 | 93 | 94 | #if USE_GSMMNG != 0 95 | gsmmng_init(); 96 | #endif 97 | } 98 | 99 | /********************** 100 | * STATIC FUNCTIONS 101 | **********************/ 102 | -------------------------------------------------------------------------------- /misc.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file misc.h 3 | * 4 | */ 5 | 6 | #ifndef MISC_H 7 | #define MISC_H 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | /********************* 14 | * INCLUDES 15 | *********************/ 16 | 17 | /********************* 18 | * DEFINES 19 | *********************/ 20 | #define MISC_VERSION_MAJOR 4 21 | #define MISC_VERSION_MINOR 2 22 | #define MISC_VERSION_PATCH 0 23 | 24 | /********************** 25 | * TYPEDEFS 26 | **********************/ 27 | 28 | /********************** 29 | * GLOBAL PROTOTYPES 30 | **********************/ 31 | 32 | /** 33 | * Initialize the enabled misc modules 34 | */ 35 | void misc_init(void); 36 | 37 | /********************** 38 | * MACROS 39 | **********************/ 40 | 41 | #ifdef __cplusplus 42 | } /* extern "C" */ 43 | #endif 44 | 45 | #endif 46 | 47 | -------------------------------------------------------------------------------- /misc_conf_templ.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file misc_conf.h 3 | * 4 | */ 5 | 6 | #if 0 /*Remove this to enable the content*/ 7 | 8 | #ifndef MISC_CONF_H 9 | #define MISC_CONF_H 10 | 11 | /*========================================= 12 | * Logging (add external log functions) 13 | *=========================================*/ 14 | #define USE_MISC_LOG 1 15 | #if USE_MISC_LOG != 0 16 | #define MISC_LOG_INCLUDE "hw/dev/ui/log.h" /*Include of log headers*/ 17 | #define MISC_LOG_MSG SMSG /*Log simple messages. (printf-like variable paremter list)*/ 18 | #define MISC_LOG_WARN SWARN /*Log warning messages. (printf-like variable paremter list)*/ 19 | #define MISC_LOG_ERR SERR /*Log error messages. (printf-like variable paremter list)*/ 20 | #endif 21 | 22 | /*==================== 23 | * Memory management 24 | *===================*/ 25 | 26 | /*---------------- 27 | * Dynamic memory 28 | *----------------*/ 29 | #define USE_DYN_MEM 1 30 | #if USE_DYN_MEM != 0 31 | #define DM_AUTO_ZERO 0 /*Automatically fill-zero the allocated memory*/ 32 | #define DM_CUSTOM 0 /*1: use custom malloc/free, 0: use malloc/free provided by dyn_mem*/ 33 | #if DM_CUSTOM == 0 34 | #define DM_MEM_SIZE (16U * 1024U) /*Size memory used by mem_alloc (in bytes)*/ 35 | #define DM_MEM_ATTR /*Complier prefix for big array declaration*/ 36 | #else /*DM_CUSTOM != 0: Provide custom malloc/free functions*/ 37 | #define DM_CUST_INCLUDE /*Header for the dynamic memory function*/ 38 | #define DM_CUST_ALLOC malloc /*Wrapper to malloc*/ 39 | #define DM_CUST_FREE free /*Wrapper to free*/ 40 | #endif /*DM_CUSTOM*/ 41 | #endif /*USE_DYN_MEM*/ 42 | 43 | /*-------------------------------------- 44 | * Dynamic memory with always 0 % fragmentation 45 | * Not compatible with normal malloc/free 46 | *------------------------------------*/ 47 | #define USE_DYN_MEM_DEFR 0 48 | #if USE_DYN_MEM_DEFR != 0 49 | #define DMD_MEM_SIZE (16U * 1024U) /*Size memory used by mem_alloc (in bytes)*/ 50 | #define DMD_AUTO_ZERO 1 /*Automatically fill-zero the allocated memory*/ 51 | #define DMD_MEM_ATTR 52 | #endif /*USE_DYN_MEM_DEFR*/ 53 | 54 | /*------------ 55 | * FIFO 56 | *-----------*/ 57 | #define USE_FIFO 0 58 | #if USE_FIFO != 0 59 | /* No settings*/ 60 | #endif /*USE_FIFO*/ 61 | 62 | /*---------------- 63 | * Linked list 64 | *----------------*/ 65 | #define USE_LINKED_LIST 1 66 | #if USE_LINKED_LIST != 0 67 | /* No settings*/ 68 | #endif /*USE_LINKED_LIST*/ 69 | 70 | /*==================== 71 | * Operation system 72 | *===================*/ 73 | 74 | /*---------------- 75 | * Periodic task 76 | *----------------*/ 77 | #define USE_PTASK 1 78 | #if USE_PTASK != 0 79 | #define PTASK_IDLE_PERIOD 500 /*500*/ 80 | #endif /*USE_PTASK*/ 81 | 82 | /*----------------------- 83 | * CPU Idle measurement 84 | *-----------------------*/ 85 | /*In hal/systick.c: systick_add_cb() and systick_rem_cb() is required)*/ 86 | #define USE_IDLE 0 87 | #if USE_IDLE != 0 88 | #define IDLE_REFR_RATE 500 /*ms*/ 89 | #endif /*USE_IDLE*/ 90 | 91 | /*=================== 92 | * File system 93 | *==================*/ 94 | 95 | /*---------------- 96 | * FS interface 97 | *----------------*/ 98 | #define USE_FSINT 1 99 | #if USE_FSINT != 0 100 | /*No settings*/ 101 | #endif /*USE_FSINT*/ 102 | 103 | /*---------------- 104 | * uFS 105 | *----------------*/ 106 | #define USE_UFS 1 107 | #if USE_UFS != 0 108 | #define UFS_LETTER 'U' 109 | #endif /*USE_UFS*/ 110 | 111 | /*------------------------ 112 | * FAT32 - FatFS wrappers 113 | * (used on MCU) 114 | *-----------------------*/ 115 | #define USE_FAT32 0 116 | #if USE_FAT32 != 0 117 | #define FAT32_LETTER 'S'/ 118 | #endif /*USE_FAT32*/ 119 | 120 | /*--------------------- 121 | * Linux File system 122 | *---------------------*/ 123 | #define USE_LINUXFS 0 124 | #if USE_LINUXFS != 0 125 | #define LINUXFS_LETTER 'L' 126 | #define LINUXFS_ROOT_DIR "./" /*See this directory as root folder*/ 127 | #endif /*USE_LINUXFS*/ 128 | 129 | /*================ 130 | * Math 131 | *================*/ 132 | 133 | /*----------------- 134 | * Trigonometry 135 | *----------------*/ 136 | #define USE_TRIGO 1 137 | #if USE_TRIGO != 0 138 | /*No settings*/ 139 | #endif 140 | 141 | /*----------------- 142 | * Math basic 143 | *----------------*/ 144 | #define USE_MATH_BASE 1 145 | #if USE_MATH_BASE != 0 146 | /*No settings*/ 147 | #endif 148 | 149 | 150 | /*=================== 151 | * GRAPHICS (GFX) 152 | *==================*/ 153 | 154 | /*---------------- 155 | * Color 156 | *----------------*/ 157 | #define USE_COLOR 1 158 | #if USE_COLOR != 0 159 | #define COLOR_DEPTH 16 160 | #endif 161 | 162 | /*---------------- 163 | * Area 164 | *----------------*/ 165 | #define USE_AREA 1 166 | #if USE_AREA != 0 167 | /*No settings*/ 168 | #endif 169 | 170 | /*---------------- 171 | * Circle 172 | *----------------*/ 173 | #define USE_CIRC 1 174 | #if USE_CIRC != 0 175 | /*No settings*/ 176 | #endif 177 | 178 | /*---------------- 179 | * Font 180 | *----------------*/ 181 | #define USE_FONT 1 182 | #if USE_FONT != 0 183 | #define FONT_BUILTIN_LATIN_EXT 0 184 | #define FONT_ANTIALIAS 0 185 | /*Built-in font usage*/ 186 | #define USE_FONT_DEJAVU_8 0 187 | #define USE_FONT_DEJAVU_10 0 188 | #define USE_FONT_DEJAVU_14 0 189 | #define USE_FONT_DEJAVU_20 0 190 | #define USE_FONT_DEJAVU_30 1 191 | #define USE_FONT_DEJAVU_40 0 192 | #define USE_FONT_DEJAVU_60 0 193 | #define USE_FONT_DEJAVU_80 0 194 | #define USE_FONT_DEJAVU_120 0 195 | #define USE_FONT_SYMBOL_30 1 196 | #define USE_FONT_SYMBOL_60 0 197 | 198 | /*Always set a default font from the built-in fonts*/ 199 | #define FONT_DEFAULT FONT_DEJAVU_30 200 | 201 | /*Enumerate the name of the external fonts. E.g: MY_FONT_1, MY_FONT_2, (comma at the end!)*/ 202 | #define FONT_NEW_NAMES 203 | 204 | #endif /*USE_FONT*/ 205 | 206 | /*---------------- 207 | * Text 208 | *----------------*/ 209 | #define USE_TEXT 1 210 | #if USE_TEXT != 0 211 | #define TXT_BREAK_CHARS " ,.;-_" /*Can break texts on these chars*/ 212 | #endif /*USE_TEXT*/ 213 | 214 | 215 | /*---------------- 216 | * Animation 217 | *----------------*/ 218 | #define USE_ANIM 1 219 | #if USE_ANIM != 0 220 | #define ANIM_REFR_PERIOD 10 /*ms*/ 221 | #endif 222 | 223 | /*=================== 224 | * Communication 225 | *==================*/ 226 | 227 | /*------------------ 228 | * WiFi Manager 229 | *-----------------*/ 230 | #define USE_WIFIMNG 0 231 | #if USE_WIFIMNG != 0 232 | #define WIFIMNG_TCP_CON_DELAY 5000 /*Delay after network connection and before connecting to TCP [ms]*/ 233 | #define WIFIMNG_RETRY_WAIT 10000 /*Wait before two reconnect attempts [ms] */ 234 | #endif 235 | 236 | /*------------------ 237 | * GSM Manager 238 | *-----------------*/ 239 | #define USE_GSMMNG 0 240 | #if USE_GSMMNG != 0 241 | #define GSMMNG_TCP_CON_DELAY 5000 /*Delay after network connection and before connecting to TCP [ms]*/ 242 | #define GSMMNG_RETRY_WAIT 10000 /*Wait before two reconnect attempts [ms] */ 243 | #endif 244 | 245 | /*=================== 246 | * Others 247 | *==================*/ 248 | 249 | /*------------ 250 | * Slip 251 | *-----------*/ 252 | #define USE_SLIP 0 253 | #if USE_SLIP != 0 254 | #define SLIP_ESC 0x0C 255 | #define SLIP_END 0xDB 256 | #define SLIP_ESC_END 0xDC /*Change END char in the stream to: ESC, ESC_END*/ 257 | #define SLIP_ESC_ESC 0xDD /*Change ESC char in the stream to: ESC, ESC_ESC*/ 258 | #endif /*USE_SLIP*/ 259 | 260 | /*---------------- 261 | * String command 262 | *--------------*/ 263 | #define USE_STRCMD 0 264 | #if USE_STRCMD != 0 265 | /*No settings*/ 266 | #endif /*USE_STRCMD*/ 267 | 268 | 269 | #endif /* MISC_CONF_H */ 270 | 271 | #endif /*Remove this to enable the content*/ 272 | -------------------------------------------------------------------------------- /os/idle.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file idle.c 3 | * Measure the CPU load by measuring how long can CPU count (increment the variable) 4 | * if do nothing else in reference time. 5 | * After it in the main loop also counts. 6 | * The ratio of the last count in given time and the reference count will give the idle ratio. 7 | */ 8 | 9 | /********************* 10 | * INCLUDES 11 | *********************/ 12 | #include "../../misc_conf.h" 13 | #if USE_IDLE != 0 14 | 15 | #include "hal/systick/systick.h" 16 | 17 | /********************* 18 | * DEFINES 19 | *********************/ 20 | #define IDLE_REF_MEAS_TIME 100 /*Start up reference measurement time in ms*/ 21 | 22 | /********************** 23 | * TYPEDEFS 24 | **********************/ 25 | 26 | /********************** 27 | * STATIC PROTOTYPES 28 | **********************/ 29 | static void idle_meas_cb(void); 30 | static void idle_meas(void); 31 | 32 | /********************** 33 | * STATIC VARIABLES 34 | **********************/ 35 | static volatile uint16_t idle_meas_interval = 1; /*The current measure interval*/ 36 | static volatile uint32_t idle_cnt = 0; /*Store the current counting*/ 37 | static volatile uint32_t idle_cnt_last = 0; /*Saved idle counter from the last round*/ 38 | static volatile uint8_t idle_null = 0; /*Query to clear the idle counter*/ 39 | static uint32_t idle_cnt_ref = 1; /*Reference counter store the count for 0% CPU load*/ 40 | 41 | /********************** 42 | * MACROS 43 | **********************/ 44 | 45 | /********************** 46 | * GLOBAL FUNCTIONS 47 | **********************/ 48 | /** 49 | * Init the idle module. It will make a reference measurement. 50 | */ 51 | void idle_init(void) 52 | { 53 | /*Set the reference measurement time*/ 54 | idle_meas_interval = IDLE_REF_MEAS_TIME; 55 | 56 | systick_add_cb(idle_meas_cb); 57 | 58 | while(idle_cnt_last == 0) { 59 | idle_meas(); 60 | } 61 | 62 | /*We know how many counts occurred in a reference time. 63 | * Now calculate how many counts could occurred with IDLE_REFR_RATE */ 64 | idle_cnt_ref = (uint32_t)((uint32_t)idle_cnt_last * IDLE_REFR_RATE) / 65 | IDLE_REF_MEAS_TIME; 66 | 67 | /*Set up for the normal idle measurement*/ 68 | idle_meas_interval = IDLE_REFR_RATE; 69 | idle_cnt_last = idle_cnt_ref; /*Until the first meas. show 100% idle*/ 70 | } 71 | 72 | /** 73 | * Return with the measured CPU idle percentage 74 | * @return The CPU idle in percentage 75 | */ 76 | uint8_t idle_get(void) 77 | { 78 | uint32_t cnt_tmp = idle_cnt_last; 79 | 80 | uint8_t idle_pct = (uint32_t)((uint32_t)cnt_tmp * 100 / idle_cnt_ref); 81 | 82 | return idle_pct; 83 | } 84 | 85 | /** 86 | * Use it instead of an empty while(1) loop to measure the idle time 87 | */ 88 | void idle_loop(void) 89 | { 90 | volatile uint32_t stop = 0; 91 | while(stop == 0) idle_meas(); 92 | } 93 | 94 | 95 | /********************** 96 | * STATIC FUNCTIONS 97 | **********************/ 98 | 99 | /** 100 | * Call in every ms to save 'idle_cnt' 101 | */ 102 | static void idle_meas_cb(void) 103 | { 104 | static uint16_t ms = 0; 105 | 106 | ms++; 107 | if(ms == idle_meas_interval) { 108 | idle_cnt_last = idle_cnt; 109 | idle_null = 1; 110 | idle_cnt = 0; 111 | ms = 0; 112 | } 113 | } 114 | 115 | /** 116 | * Used in idle_loop to measure the idle time 117 | */ 118 | static void idle_meas(void) 119 | { 120 | /* Interesting: On assembly level the old value of idle_cnt can be kept so 121 | * clear is here as well not only in the interrupt */ 122 | if(idle_null == 1 && idle_cnt != 0) 123 | { 124 | idle_null = 0; 125 | idle_cnt = 0; 126 | } 127 | 128 | /* Increment the idle_cnt 129 | * It will show how long was the CPU in the main loop. 130 | * If it is a smaller value then it was a lot of interrupt 131 | * so the CPU load is big */ 132 | idle_cnt++; 133 | } 134 | 135 | 136 | #endif 137 | -------------------------------------------------------------------------------- /os/idle.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file idle.h 3 | * Measure the CPU load by measuring how long can CPU count (increment the variable) 4 | * if do nothing else in reference time. 5 | * After it in the main loop also counts. 6 | * The ratio of the last count in given time and the reference count will give the idle ratio. 7 | */ 8 | 9 | #ifndef IDLE_H 10 | #define IDLE_H 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | /********************* 17 | * INCLUDES 18 | *********************/ 19 | #include "../../misc_conf.h" 20 | #if USE_IDLE != 0 21 | 22 | #include 23 | 24 | /********************* 25 | * DEFINES 26 | *********************/ 27 | 28 | /********************** 29 | * TYPEDEFS 30 | **********************/ 31 | 32 | /********************** 33 | * GLOBAL PROTOTYPES 34 | **********************/ 35 | 36 | /** 37 | * Init the idle module. It will make a reference measurement. 38 | */ 39 | void idle_init(void); 40 | 41 | /** 42 | * Return with the measured CPU idle in percentage 43 | * @return The CPU idle in percentage 44 | */ 45 | uint8_t idle_get(void); 46 | 47 | /** 48 | * Use it instead of an empty while(1) loop to measure the idle time 49 | */ 50 | void idle_loop(void); 51 | 52 | /********************** 53 | * MACROS 54 | **********************/ 55 | 56 | #endif 57 | 58 | #ifdef __cplusplus 59 | } /* extern "C" */ 60 | #endif 61 | 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /os/ptask.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file ptask.c 3 | * A Periodic Tasks is a void (*fp) (void) type function which will be called periodically. 4 | * A priority (5 levels + disable) can be assigned to ptasks. 5 | */ 6 | 7 | /********************* 8 | * INCLUDES 9 | *********************/ 10 | #include "../../misc_conf.h" 11 | #if USE_PTASK != 0 12 | 13 | 14 | #include "ptask.h" 15 | #include 16 | #include "hal/systick/systick.h" 17 | 18 | /********************* 19 | * DEFINES 20 | *********************/ 21 | 22 | /********************** 23 | * TYPEDEFS 24 | **********************/ 25 | 26 | /********************** 27 | * STATIC PROTOTYPES 28 | **********************/ 29 | static bool ptask_exec(ptask_t* ptask_p, ptask_prio_t prio_act); 30 | 31 | /********************** 32 | * STATIC VARIABLES 33 | **********************/ 34 | static ll_dsc_t ptask_ll; /*Linked list to store the ptasks*/ 35 | static bool ptask_run = false; 36 | static uint8_t idle_last = 0; 37 | 38 | /********************** 39 | * MACROS 40 | **********************/ 41 | 42 | /********************** 43 | * GLOBAL FUNCTIONS 44 | **********************/ 45 | 46 | /** 47 | * Init the ptask module 48 | */ 49 | void ptask_init(void) 50 | { 51 | ll_init(&ptask_ll, sizeof(ptask_t)); 52 | 53 | /*Initially enable the ptask handling*/ 54 | ptask_en(true); 55 | } 56 | 57 | /** 58 | * Call it periodically to handle ptasks. 59 | */ 60 | void ptask_handler(void) 61 | { 62 | if(ptask_run == false) return; 63 | 64 | static uint32_t idle_tick = 0; 65 | static uint32_t used_tick = 0; 66 | uint32_t start_tick = systick_get(); 67 | 68 | if(idle_tick == 0) idle_tick = systick_get(); 69 | 70 | ptask_t* ptask_prio_a[PTASK_PRIO_NUM]; /*Lists for all prio.*/ 71 | ptask_prio_t prio_act; 72 | bool prio_reset = false; /*Used to go back to the highest priority*/ 73 | ptask_t* ptask_next; 74 | 75 | /*Init. the lists*/ 76 | for(prio_act = PTASK_PRIO_LOWEST; prio_act <= PTASK_PRIO_HIGHEST; prio_act++) { 77 | ptask_prio_a[prio_act] = ll_get_head(&ptask_ll); 78 | } 79 | 80 | /*Handle the ptasks on all priority*/ 81 | for(prio_act = PTASK_PRIO_HIGHEST; prio_act > PTASK_PRIO_OFF; prio_act --) { 82 | /*Reset the prio. if necessary*/ 83 | if(prio_reset != false) { 84 | prio_reset = false; 85 | prio_act = PTASK_PRIO_HIGHEST; /*Go again with highest prio */ 86 | } 87 | 88 | /* Read all ptask on 'prio_act' but stop on 'prio_reset' */ 89 | while(ptask_prio_a[prio_act] != NULL && prio_reset == false) { 90 | /* Get the next task. (Invalid pointer if a ptask deletes itself)*/ 91 | ptask_next = ll_get_next(&ptask_ll, ptask_prio_a[prio_act]); 92 | 93 | /*Execute the current ptask*/ 94 | bool executed = ptask_exec(ptask_prio_a[prio_act], prio_act); 95 | if(executed != false) { /*If the task is executed*/ 96 | /* During the execution higher priority ptasks 97 | * can be ready, so reset the priority if it is not highest*/ 98 | if(prio_act != PTASK_PRIO_HIGHEST) { 99 | prio_reset = true; 100 | } 101 | } 102 | 103 | ptask_prio_a[prio_act] = ptask_next; /*Load the next task*/ 104 | } 105 | 106 | /*Reset higher priority lists on 'prio_reset' query*/ 107 | if(prio_reset != false) { 108 | for(prio_act = prio_act + 1; prio_act <= PTASK_PRIO_HIGHEST; prio_act++) { 109 | ptask_prio_a[prio_act] = ll_get_head(&ptask_ll); 110 | } 111 | } 112 | } 113 | 114 | used_tick += systick_elaps(start_tick); 115 | if(systick_elaps(idle_tick) > PTASK_IDLE_PERIOD) { 116 | idle_last = (uint32_t)((uint32_t) used_tick * 100) / systick_elaps(idle_tick); /*Calculate the busy time*/ 117 | idle_last = idle_last > 100 ? 0 : 100 - idle_last; /*Convert he busy time to idle time*/ 118 | idle_tick = 0; 119 | used_tick = 0; 120 | } 121 | } 122 | 123 | /** 124 | * Create a new ptask 125 | * @param task a function which is the task itself 126 | * @param period call period in ms unit 127 | * @param prio priority of the task (PTASK_PRIO_OFF means the task is stopped) 128 | * @param param free parameter 129 | * @return pointer to the new task 130 | */ 131 | ptask_t* ptask_create(void (*task) (void *), uint32_t period, ptask_prio_t prio, void * param) 132 | { 133 | ptask_t* new_ptask; 134 | 135 | new_ptask = ll_ins_head(&ptask_ll); 136 | dm_assert(new_ptask); 137 | 138 | new_ptask->period = period; 139 | new_ptask->task = task; 140 | new_ptask->prio = prio; 141 | new_ptask->param = param; 142 | new_ptask->once = 0; 143 | new_ptask->last_run = systick_get(); 144 | 145 | return new_ptask; 146 | } 147 | 148 | /** 149 | * Delete a ptask 150 | * @param ptask_p pointer to task created by ptask_p 151 | */ 152 | void ptask_del(ptask_t* ptask_p) 153 | { 154 | ll_rem(&ptask_ll, ptask_p); 155 | 156 | dm_free(ptask_p); 157 | } 158 | 159 | /** 160 | * Set new priority for a ptask 161 | * @param ptask_p pointer to a ptask 162 | * @param prio the new priority 163 | */ 164 | void ptask_set_prio(ptask_t* ptask_p, ptask_prio_t prio) 165 | { 166 | ptask_p->prio = prio; 167 | } 168 | 169 | /** 170 | * Set new period for a ptask 171 | * @param ptask_p pointer to a ptask 172 | * @param period the new period 173 | */ 174 | void ptask_set_period(ptask_t* ptask_p, uint32_t period) 175 | { 176 | ptask_p->period = period; 177 | } 178 | 179 | /** 180 | * Make a ptask ready. It will not wait its period. 181 | * @param ptask_p pointer to a ptask. 182 | */ 183 | void ptask_ready(ptask_t* ptask_p) 184 | { 185 | ptask_p->last_run = systick_get() - ptask_p->period - 1; 186 | } 187 | 188 | /** 189 | * Delete the ptask after one call 190 | * @param ptask_p pointer to a ptask. 191 | */ 192 | void ptask_once(ptask_t * ptask_p) 193 | { 194 | ptask_p->once = 1; 195 | } 196 | 197 | /** 198 | * Reset a ptask. 199 | * It will be called the previously set period milliseconds later. 200 | * @param ptask_p pointer to a ptask. 201 | */ 202 | void ptask_reset(ptask_t* ptask_p) 203 | { 204 | ptask_p->last_run = systick_get(); 205 | } 206 | 207 | /** 208 | * Enable or disable ptask handling 209 | * @param en: true: ptask handling is running, false: ptask handling is suspended 210 | */ 211 | void ptask_en(bool en) 212 | { 213 | ptask_run = en; 214 | } 215 | 216 | /** 217 | * Get idle percentage 218 | * @return the ptask idle in percentage 219 | */ 220 | uint8_t ptask_get_idle(void) 221 | { 222 | return idle_last; 223 | } 224 | 225 | 226 | /********************** 227 | * STATIC FUNCTIONS 228 | **********************/ 229 | 230 | /** 231 | * Execute task if its the priority is appropriate 232 | * @param ptask_p pointer to ptask 233 | * @param prio_act the current priority 234 | * @return true: execute, false: not executed 235 | */ 236 | static bool ptask_exec (ptask_t* ptask_p, ptask_prio_t prio_act) 237 | { 238 | bool exec = false; 239 | 240 | /*Execute ptask if its prio is 'prio_act'*/ 241 | if(ptask_p->prio == prio_act) { 242 | /*Execute if at least 'period' time elapsed*/ 243 | uint32_t elp = systick_elaps(ptask_p->last_run); 244 | if(elp >= ptask_p->period) { 245 | ptask_p->last_run = systick_get(); 246 | ptask_p->task(ptask_p->param); 247 | 248 | /*Delete if it was a one shot ptask*/ 249 | if(ptask_p->once != 0) ptask_del(ptask_p); 250 | 251 | exec = true; 252 | } 253 | } 254 | 255 | return exec; 256 | } 257 | 258 | 259 | #endif 260 | -------------------------------------------------------------------------------- /os/ptask.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file ptask.h 3 | * A Periodic Tasks is a void (*fp) (void) type function which will be called periodically. 4 | * A priority (5 levels + disable) can be assigned to ptasks. 5 | */ 6 | 7 | #ifndef PTASK_H 8 | #define PTASK_H 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | /********************* 15 | * INCLUDES 16 | *********************/ 17 | #include "../../misc_conf.h" 18 | 19 | #if USE_PTASK != 0 20 | #include 21 | #include 22 | #include "../mem/dyn_mem.h" 23 | #include "../mem/linked_list.h" 24 | 25 | /********************* 26 | * DEFINES 27 | *********************/ 28 | #ifndef PTASK_IDLE_PERIOD 29 | #define PTASK_IDLE_PERIOD 500 30 | #endif 31 | 32 | 33 | /********************** 34 | * TYPEDEFS 35 | **********************/ 36 | /** 37 | * Possible priorities for ptasks 38 | */ 39 | typedef enum 40 | { 41 | PTASK_PRIO_OFF = 0, 42 | PTASK_PRIO_LOWEST, 43 | PTASK_PRIO_LOW, 44 | PTASK_PRIO_MID, 45 | PTASK_PRIO_HIGH, 46 | PTASK_PRIO_HIGHEST, 47 | PTASK_PRIO_NUM, 48 | }ptask_prio_t; 49 | 50 | /** 51 | * Descriptor of a ptask 52 | */ 53 | typedef struct 54 | { 55 | uint32_t period; 56 | uint32_t last_run; 57 | void (*task) (void*); 58 | void * param; 59 | uint8_t prio:3; 60 | uint8_t once:1; 61 | }ptask_t; 62 | 63 | /********************** 64 | * GLOBAL PROTOTYPES 65 | **********************/ 66 | 67 | /** 68 | * Init the ptask module 69 | */ 70 | void ptask_init(void); 71 | 72 | /** 73 | * Call it periodically to handle ptasks. 74 | */ 75 | void ptask_handler(void); 76 | 77 | /** 78 | * Create a new ptask 79 | * @param task a function which is the task itself 80 | * @param period call period in ms unit 81 | * @param prio priority of the task (PTASK_PRIO_OFF means the task is stopped) 82 | * @param param free parameter 83 | * @return pointer to the new task 84 | */ 85 | ptask_t* ptask_create(void (*task) (void *), uint32_t period, ptask_prio_t prio, void * param); 86 | 87 | /** 88 | * Delete a ptask 89 | * @param ptask_p pointer to task created by ptask_p 90 | */ 91 | void ptask_del(ptask_t* ptask_p); 92 | 93 | /** 94 | * Set new priority for a ptask 95 | * @param ptask_p pointer to a ptask 96 | * @param prio the new priority 97 | */ 98 | void ptask_set_prio(ptask_t* ptask_p, ptask_prio_t prio); 99 | 100 | /** 101 | * Set new period for a ptask 102 | * @param ptask_p pointer to a ptask 103 | * @param period the new period 104 | */ 105 | void ptask_set_period(ptask_t* ptask_p, uint32_t period); 106 | 107 | /** 108 | * Make a ptask ready. It will not wait its period. 109 | * @param ptask_p pointer to a ptask. 110 | */ 111 | void ptask_ready(ptask_t* ptask_p); 112 | 113 | 114 | /** 115 | * Delete the ptask after one call 116 | * @param ptask_p pointer to a ptask. 117 | */ 118 | void ptask_once(ptask_t * ptask_p); 119 | 120 | /** 121 | * Reset a ptask. 122 | * It will be called the previously set period milliseconds later. 123 | * @param ptask_p pointer to a ptask. 124 | */ 125 | void ptask_reset(ptask_t* ptask_p); 126 | 127 | /** 128 | * Enable or disable ptask handling 129 | * @param en: true: ptask handling is running, false: ptask handling is suspended 130 | */ 131 | void ptask_en(bool en); 132 | 133 | uint8_t ptask_get_idle(void); 134 | 135 | /********************** 136 | * MACROS 137 | **********************/ 138 | 139 | #endif 140 | 141 | #ifdef __cplusplus 142 | } /* extern "C" */ 143 | #endif 144 | 145 | 146 | #endif 147 | -------------------------------------------------------------------------------- /others/fsm.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file fsm.c 3 | * 4 | */ 5 | 6 | /********************* 7 | * INCLUDES 8 | *********************/ 9 | #include "fsm.h" 10 | #include 11 | 12 | /********************* 13 | * DEFINES 14 | *********************/ 15 | 16 | /********************** 17 | * TYPEDEFS 18 | **********************/ 19 | 20 | /********************** 21 | * STATIC PROTOTYPES 22 | **********************/ 23 | 24 | /********************** 25 | * STATIC VARIABLES 26 | **********************/ 27 | 28 | /********************** 29 | * MACROS 30 | **********************/ 31 | 32 | /********************** 33 | * GLOBAL FUNCTIONS 34 | **********************/ 35 | void fsm_handler(fsm_t * fsm) 36 | { 37 | if(fsm->funcs[fsm->state_act] != NULL) { 38 | fsm->funcs[fsm->state_act](FSM_SUBSTATE_RUN, &fsm->param); 39 | } 40 | } 41 | 42 | 43 | void fsm_set_state(fsm_t * fsm, fsm_state_t state) 44 | { 45 | if(fsm->funcs[fsm->state_act] != NULL) { 46 | fsm->funcs[fsm->state_act](FSM_SUBSTATE_LEAVE, &fsm->param); 47 | } 48 | 49 | fsm->state_act = state; 50 | 51 | if(fsm->funcs[fsm->state_act] != NULL) { 52 | fsm->funcs[fsm->state_act](FSM_SUBSTATE_INIT, &fsm->param); 53 | } 54 | } 55 | 56 | fsm_state_t fsm_get_state(const fsm_t * fsm) 57 | { 58 | return fsm->state_act; 59 | } 60 | 61 | /********************** 62 | * STATIC FUNCTIONS 63 | **********************/ 64 | -------------------------------------------------------------------------------- /others/fsm.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file fsm.h 3 | * Finite State Machine 4 | */ 5 | 6 | #ifndef FSM_H 7 | #define FSM_H 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | 14 | /********************* 15 | * INCLUDES 16 | *********************/ 17 | #include "misc_conf.h" 18 | 19 | #include 20 | 21 | /********************* 22 | * DEFINES 23 | *********************/ 24 | 25 | /********************** 26 | * TYPEDEFS 27 | **********************/ 28 | typedef enum { 29 | FSM_SUBSTATE_INIT, 30 | FSM_SUBSTATE_RUN, 31 | FSM_SUBSTATE_LEAVE, 32 | }fsm_substate_t; 33 | 34 | typedef int16_t fsm_state_t; 35 | 36 | typedef void (*fsm_func_t)(fsm_substate_t substate, int32_t * param); 37 | 38 | typedef struct { 39 | fsm_state_t state_act; 40 | fsm_func_t * funcs; 41 | int32_t param; 42 | }fsm_t; 43 | 44 | /********************** 45 | * GLOBAL PROTOTYPES 46 | **********************/ 47 | void fsm_handler(fsm_t * fsm); 48 | void fsm_set_state(fsm_t * fsm, fsm_state_t state); 49 | fsm_state_t fsm_get_state(const fsm_t * fsm); 50 | 51 | 52 | /********************** 53 | * MACROS 54 | **********************/ 55 | 56 | 57 | #ifdef __cplusplus 58 | } /* extern "C" */ 59 | #endif 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /others/slip.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file slip.c 3 | * Implementation of SLIP protocol 4 | */ 5 | 6 | /********************* 7 | * INCLUDES 8 | *********************/ 9 | #include "../../misc_conf.h" 10 | #if USE_SLIP != 0 11 | 12 | #include "slip.h" 13 | 14 | /********************* 15 | * DEFINES 16 | *********************/ 17 | 18 | /********************** 19 | * TYPEDEFS 20 | **********************/ 21 | 22 | /********************** 23 | * STATIC PROTOTYPES 24 | **********************/ 25 | 26 | /********************** 27 | * STATIC VARIABLES 28 | **********************/ 29 | 30 | /********************** 31 | * MACROS 32 | **********************/ 33 | 34 | /********************** 35 | * GLOBAL FUNCTIONS 36 | **********************/ 37 | /** 38 | * Convert the source bytes ('src_p') according to the SLIP protocol 39 | * @param dest_p buffer for the SLIP convert bytes (size >= 'src_len' * 2 + 1) 40 | * @param src_p pointer to the non-SLIPed data 41 | * @param src_len the length of 'src_p' array in bytes 42 | * @return the length of 'dest_p' array in bytes 43 | */ 44 | uint32_t slip_encode(void * dest_p, void * src_p, uint32_t src_len) 45 | { 46 | uint32_t dest_pct = 0; /*The currently written byte in 'dest'*/ 47 | uint32_t i; 48 | uint8_t * src8_p = src_p; /*Use byte arrays when process the data*/ 49 | uint8_t * dest8_p = dest_p; 50 | #if SLIP_END_FIRST != 0 51 | /*Add a starting END character*/ 52 | dest8_p[dest_pct] = SLIP_END; 53 | dest_pct ++; 54 | #endif 55 | 56 | /*Convert all bytes*/ 57 | for(i = 0; i < src_len; i++) { 58 | switch(src8_p[i]) { 59 | /*Change END chars to ESC, ESC_END*/ 60 | case SLIP_END: 61 | dest8_p[dest_pct] = SLIP_ESC; 62 | dest_pct ++; 63 | dest8_p[dest_pct] = SLIP_ESC_END; 64 | dest_pct ++; 65 | break; 66 | /*Change ESC chars to ESC, ESC_ESC*/ 67 | case SLIP_ESC: 68 | dest8_p[dest_pct] = SLIP_ESC; 69 | dest_pct ++; 70 | dest8_p[dest_pct] = SLIP_ESC_ESC; 71 | dest_pct ++; 72 | break; 73 | /*Simply copy non-special characters*/ 74 | default: 75 | dest8_p[dest_pct] = src8_p[i]; 76 | dest_pct ++; 77 | } 78 | } 79 | 80 | #if SLIP_END_FIRST == 0 81 | /*Add a closing END character*/ 82 | dest8_p[dest_pct] = SLIP_END; 83 | dest_pct ++; 84 | #endif 85 | 86 | return dest_pct; 87 | } 88 | 89 | /** 90 | * Init a 'slip_proc_t' variable to can be used in 'slip_proc_byte' 91 | * @param slip_p pointer to a slip_proc_t variable 92 | * @param buf_p a buffer to store decoded SLIP stream 93 | * @param buf_size the size of buffer in bytes 94 | */ 95 | void slip_proc_init(slip_proc_t * slip_p, void * buf_p, uint32_t buf_size) 96 | { 97 | slip_p->buf = buf_p; 98 | slip_p->buf_size = buf_size; 99 | slip_p->data_cnt = 0; 100 | slip_p->escaping = 0; 101 | slip_p->ready = 0; 102 | } 103 | 104 | /** 105 | * Decode the SLIP coded bytes of a stream 106 | * @param slip_p inited by 'slip_proc_init' 107 | * @param next_data the next data of the stream 108 | * @return SLIP_READY: ready message in buffe. Get its length with: 'slip_proc_get_length' 109 | * SLIP_WAIT: not ready, waiting for the next byte 110 | * any error from 'slip_res_t' 111 | */ 112 | slip_res_t slip_proc_byte(slip_proc_t * slip_p, uint8_t next_data) 113 | { 114 | slip_res_t res = SLIP_WAIT; 115 | 116 | if(slip_p->ready != 0) { /*Reset if it was a ready message*/ 117 | slip_p->data_cnt = 0; 118 | slip_p->ready = 0; 119 | } 120 | 121 | if(slip_p->escaping != 0) { /*Handle the escaping*/ 122 | switch(next_data) { 123 | case SLIP_ESC_ESC: 124 | slip_p->buf[slip_p->data_cnt] = SLIP_ESC; 125 | break; 126 | case SLIP_ESC_END: 127 | slip_p->buf[slip_p->data_cnt] = SLIP_END; 128 | break; 129 | default: 130 | res = SLIP_PROT_ERR; 131 | } 132 | slip_p->escaping = 0; 133 | } else if (next_data == SLIP_END) { /*Finish if non-escaped END*/ 134 | slip_p->ready = 1; 135 | res = SLIP_READY; 136 | } else if (next_data == SLIP_ESC) { 137 | slip_p->escaping = 1; 138 | } 139 | else { /*Save normal data*/ 140 | slip_p->buf[slip_p->data_cnt] = next_data; 141 | } 142 | 143 | if(res == SLIP_WAIT && next_data != SLIP_ESC) { 144 | slip_p->data_cnt ++; 145 | } 146 | if(slip_p->data_cnt == slip_p->buf_size) { 147 | slip_p->data_cnt = 0; 148 | res = SLIP_LONG; 149 | } 150 | 151 | return res; 152 | } 153 | 154 | /** 155 | * Gives the length of a READY message decoded by 'slip_proc_bytes' 156 | * @param slip_p pointer to a slip_proc_t variable which was used in 'slip_proc_byte' 157 | * @return length of the decoded message in bytes 158 | */ 159 | uint32_t slip_proc_get_msg_length(const slip_proc_t * slip_p) 160 | { 161 | if(slip_p->ready != 0) return slip_p->data_cnt; 162 | else return 0; 163 | } 164 | 165 | /********************** 166 | * STATIC FUNCTIONS 167 | **********************/ 168 | 169 | #endif 170 | -------------------------------------------------------------------------------- /others/slip.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file slip.h 3 | * 4 | */ 5 | 6 | #ifndef SLIP_H 7 | #define SLIP_H 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | 14 | /********************* 15 | * INCLUDES 16 | *********************/ 17 | #include "../../misc_conf.h" 18 | #if USE_SLIP != 0 19 | 20 | #include 21 | #include 22 | 23 | /********************* 24 | * DEFINES 25 | *********************/ 26 | 27 | /********************** 28 | * TYPEDEFS 29 | **********************/ 30 | typedef enum 31 | { 32 | SLIP_READY, /*Message is ready in buffer*/ 33 | SLIP_WAIT, /*Waiting for the next byte*/ 34 | SLIP_LONG, /*Buffer is not big enough for the message*/ 35 | SLIP_PROT_ERR, /*Protocol error*/ 36 | }slip_res_t; 37 | 38 | typedef struct 39 | { 40 | uint8_t * buf; 41 | uint32_t buf_size; 42 | uint32_t data_cnt; 43 | uint8_t escaping :1; 44 | uint8_t ready :1; 45 | }slip_proc_t; 46 | 47 | /********************** 48 | * GLOBAL PROTOTYPES 49 | **********************/ 50 | 51 | /** 52 | * Convert the source bytes ('src_p') according to the SLIP protocol 53 | * @param dest_p buffer for the SLIP convert bytes (size >= 'src_len' * 2 + 1) 54 | * @param src_p pointer to the non-SLIPed data 55 | * @param src_len the length of 'src_p' array in bytes 56 | * @return the length of 'dest_p' array in bytes 57 | */ 58 | uint32_t slip_encode(void * dest_p, void * src_p, uint32_t src_len); 59 | 60 | /** 61 | * Init a 'slip_proc_t' variable to can be used in 'slip_proc_byte' 62 | * @param slip_p pointer to a slip_proc_t variable 63 | * @param buf_p a buffer to store decoded SLIP stream 64 | * @param buf_size the size of buffer in bytes 65 | */ 66 | void slip_proc_init(slip_proc_t * slip_p, void * buf_p, uint32_t buf_size); 67 | 68 | /** 69 | * Decode the SLIP coded bytes of a stream 70 | * @param slip_p inited by 'slip_proc_init' 71 | * @param next_data the next data of the stream 72 | * @return SLIP_READY: ready message in buffe. Get its length with: 'slip_proc_get_length' 73 | * SLIP_WAIT: not ready, waiting for the next byte 74 | * any error from 'slip_res_t' 75 | */ 76 | slip_res_t slip_proc_byte(slip_proc_t * slip_p, uint8_t next_data); 77 | 78 | /** 79 | * Gives the length of a READY message decoded by 'slip_proc_bytes' 80 | * @param slip_p pointer to a slip_proc_t variable which was used in 'slip_proc_byte' 81 | * @return length of the decoded message in bytes 82 | */ 83 | uint32_t slip_proc_get_msg_length(const slip_proc_t * slip_p); 84 | 85 | /********************** 86 | * MACROS 87 | **********************/ 88 | 89 | #endif 90 | 91 | 92 | #ifdef __cplusplus 93 | } /* extern "C" */ 94 | #endif 95 | 96 | #endif 97 | -------------------------------------------------------------------------------- /others/strcmd.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file strcmd.c 3 | * String Command parser. Waits for "\r\n" terminated commands. 4 | * E.g.: "operation=measure\r\n" 5 | */ 6 | 7 | /********************* 8 | * INCLUDES 9 | *********************/ 10 | #include "../../misc_conf.h" 11 | #if USE_STRCMD != 0 12 | 13 | #include 14 | #include "strcmd.h" 15 | 16 | /********************* 17 | * DEFINES 18 | *********************/ 19 | 20 | /********************** 21 | * TYPEDEFS 22 | **********************/ 23 | 24 | /********************** 25 | * STATIC PROTOTYPES 26 | **********************/ 27 | static int16_t strcmd_test(sc_t * sc_p) ; 28 | 29 | /********************** 30 | * STATIC VARIABLES 31 | **********************/ 32 | 33 | /********************** 34 | * MACROS 35 | **********************/ 36 | 37 | /********************** 38 | * GLOBAL FUNCTIONS 39 | **********************/ 40 | 41 | /** 42 | * Initialize a string command variable 43 | * @param sc_p pointer to a sc_t variable to initalize 44 | * @param cmds the possible commands as an array of character strings. 45 | * The last command has to be "". 46 | * @param buf a buffer to store commands during the process (size > longest command + parameter + 8) 47 | * @param buf_len length of 'buf' in bytes. 48 | */ 49 | void strcmd_init(sc_t * sc_p, const char ** cmds, char *buf, uint16_t buf_len) 50 | { 51 | sc_p->cmds = cmds; 52 | sc_p->bufp = buf; 53 | sc_p->buf_len = buf_len; 54 | sc_p->bufi = 0; 55 | sc_p->state = SC_WAIT; 56 | sc_p->last_cmd = STRCMD_NOT_READY; 57 | sc_p->par = 0; 58 | } 59 | 60 | /** 61 | * Add a character to process. 62 | * @param sc_p pointer to an initialized sc_t variable 63 | * @param c a character to add 64 | * @return >= 0: id of the received command, < 0 not ready or error, see strcmd.h for return codes 65 | */ 66 | int16_t strcmd_add(sc_t * sc_p, char c) 67 | { 68 | sc_state_t res = STRCMD_NOT_READY; 69 | 70 | switch(sc_p->state) { 71 | case SC_WAIT: 72 | if(c != '\r' && c != '\n') { 73 | sc_p->bufp[0] = c; 74 | sc_p->bufi = 1; 75 | sc_p->state = SC_CMD_REC; 76 | sc_p->par = 0; 77 | sc_p->last_cmd = STRCMD_NOT_READY; 78 | } 79 | break; 80 | 81 | case SC_CMD_REC: 82 | if(sc_p->bufi >= sc_p->buf_len) { 83 | sc_p->state = SC_WAIT; /*Buffer overflow*/ 84 | sc_p->bufp[0] = '\0'; 85 | res = STRCMD_OVERFLOW; 86 | } else { 87 | if(c == '\r') { 88 | /*Save the command*/ 89 | sc_p->bufp[sc_p->bufi] = '\0'; /*Convert to string*/ 90 | sc_p->last_cmd = strcmd_test(sc_p); 91 | sc_p->state = SC_N_REC; /*Command end*/ 92 | } else if(c == '=') { /*Parameter will come after '='*/ 93 | /*Save the command*/ 94 | sc_p->bufp[sc_p->bufi] = '\0'; /*Convert to string*/ 95 | sc_p->last_cmd = strcmd_test(sc_p); 96 | sc_p->state = SC_PAR_REC; 97 | sc_p->bufi = 0; 98 | sc_p->par = 1; 99 | } else { 100 | sc_p->bufp[sc_p->bufi] = c; 101 | sc_p->bufi ++; 102 | } 103 | } 104 | break; 105 | 106 | case SC_PAR_REC: 107 | if(sc_p->bufi >= sc_p->buf_len) { 108 | sc_p->state = SC_WAIT; /*Buffer overflow*/ 109 | sc_p->bufp[0] = '\0'; 110 | res = STRCMD_OVERFLOW; 111 | } else { 112 | if(c == '\r') { 113 | sc_p->bufp[sc_p->bufi] = '\0'; /*Convert to string*/ 114 | sc_p->state = SC_N_REC; /*Parameter end*/ 115 | } else { 116 | sc_p->bufp[sc_p->bufi] = c; 117 | sc_p->bufi ++; 118 | } 119 | } 120 | break; 121 | 122 | case SC_N_REC: 123 | if(c != '\n') { 124 | sc_p->last_cmd = STRCMD_FORMAT_ERR; 125 | } 126 | sc_p->state = SC_WAIT; 127 | 128 | res = sc_p->last_cmd; 129 | break; 130 | } 131 | 132 | return res; 133 | } 134 | 135 | /** 136 | * Return with parameter of the last command. 137 | * @param sc_p pointer to an 'sc_t' variable. 138 | * @return the parameter as string or "" if no parameter 139 | */ 140 | const char * strcmd_get_par(sc_t * sc_p) 141 | { 142 | if(sc_p->par == 0) return ""; 143 | else return sc_p->bufp; 144 | } 145 | 146 | /********************** 147 | * STATIC FUNCTIONS 148 | **********************/ 149 | 150 | /** 151 | * Test the current string if it is a valid command or not 152 | * @param sc_p pointer to a 'sc_t' variable 153 | * @return >= 0: id of a command, STRCMD_UNKNOWN: no matching command found 154 | */ 155 | static int16_t strcmd_test(sc_t * sc_p) 156 | { 157 | uint16_t i; 158 | for(i = 0; sc_p->cmds[i][0] != '\0'; i++) { 159 | if(strcmp(sc_p->bufp, sc_p->cmds[i]) == 0) return i; 160 | } 161 | 162 | return STRCMD_UNKNOWN; 163 | } 164 | #endif 165 | -------------------------------------------------------------------------------- /others/strcmd.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file strcmd.h 3 | * 4 | */ 5 | 6 | #ifndef STRCMD_H 7 | #define STRCMD_H 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | 14 | /********************* 15 | * INCLUDES 16 | *********************/ 17 | #include "../../misc_conf.h" 18 | #if USE_STRCMD != 0 19 | 20 | #include 21 | 22 | /********************* 23 | * DEFINES 24 | *********************/ 25 | /*Return codes*/ 26 | #define STRCMD_NOT_READY (-1) 27 | #define STRCMD_UNKNOWN (-2) 28 | #define STRCMD_FORMAT_ERR (-3) 29 | #define STRCMD_OVERFLOW (-4) 30 | 31 | /********************** 32 | * TYPEDEFS 33 | **********************/ 34 | 35 | /*Internal states of command processing*/ 36 | typedef enum 37 | { 38 | SC_WAIT, /*Wait for the first data*/ 39 | SC_CMD_REC, /*Receiving command*/ 40 | SC_PAR_REC, /*Receiving paramter*/ 41 | SC_N_REC, /*Wait for \n*/ 42 | }sc_state_t; 43 | 44 | typedef struct 45 | { 46 | const char ** cmds; 47 | char * bufp; 48 | uint16_t buf_len; 49 | uint16_t bufi; 50 | sc_state_t state; 51 | int16_t last_cmd; 52 | uint8_t par :1; /*The command has paramter*/ 53 | }sc_t; 54 | 55 | /********************** 56 | * GLOBAL PROTOTYPES 57 | **********************/ 58 | 59 | /** 60 | * Initialize a string command variable 61 | * @param sc_p pointer to a sc_t variable to initalize 62 | * @param cmds the possible commands as an array of character strings. 63 | * The last command has to be "". 64 | * @param buf a buffer to store commands during the process (size > longest command + parameter + 8) 65 | * @param buf_len length of 'buf' in bytes. 66 | */ 67 | void strcmd_init(sc_t * sc_p, const char ** cmds, char *buf, uint16_t buf_len); 68 | 69 | /** 70 | * Add a character to process. 71 | * @param sc_p pointer to an initialized sc_t variable 72 | * @param c a character to add 73 | * @return >= 0: id of the received command, < 0 not ready or error, see strcmd.h for return codes 74 | */ 75 | int16_t strcmd_add(sc_t * sc_p, char c); 76 | 77 | /** 78 | * Return with parameter of the last command. 79 | * @param sc_p pointer to an 'sc_t' variable. 80 | * @return the parameter as string or "" if no parameter 81 | */ 82 | const char * strcmd_get_par(sc_t * sc_p); 83 | 84 | /********************** 85 | * MACROS 86 | **********************/ 87 | 88 | #endif /*USE_STRCMD*/ 89 | 90 | #ifdef __cplusplus 91 | } /* extern "C" */ 92 | #endif 93 | 94 | #endif 95 | -------------------------------------------------------------------------------- /templ/templ.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file templ.c 3 | * 4 | */ 5 | 6 | /********************* 7 | * INCLUDES 8 | *********************/ 9 | 10 | /********************* 11 | * DEFINES 12 | *********************/ 13 | 14 | /********************** 15 | * TYPEDEFS 16 | **********************/ 17 | 18 | /********************** 19 | * STATIC PROTOTYPES 20 | **********************/ 21 | 22 | /********************** 23 | * STATIC VARIABLES 24 | **********************/ 25 | 26 | /********************** 27 | * MACROS 28 | **********************/ 29 | 30 | /********************** 31 | * GLOBAL FUNCTIONS 32 | **********************/ 33 | 34 | /********************** 35 | * STATIC FUNCTIONS 36 | **********************/ -------------------------------------------------------------------------------- /templ/templ.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file templ.h 3 | * 4 | */ 5 | 6 | #ifndef TEMPL_H 7 | #define TEMPL_H 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | /********************* 14 | * INCLUDES 15 | *********************/ 16 | 17 | /********************* 18 | * DEFINES 19 | *********************/ 20 | 21 | /********************** 22 | * TYPEDEFS 23 | **********************/ 24 | 25 | /********************** 26 | * GLOBAL PROTOTYPES 27 | **********************/ 28 | 29 | /********************** 30 | * MACROS 31 | **********************/ 32 | 33 | 34 | #ifdef __cplusplus 35 | } /* extern "C" */ 36 | #endif 37 | 38 | #endif /*TEMPL_H*/ 39 | --------------------------------------------------------------------------------