2 * This file is part of Cleanflight and Betaflight.
4 * Cleanflight and Betaflight are free software. You can redistribute
5 * this software and/or modify this software under the terms of the
6 * GNU General Public License as published by the Free Software
7 * Foundation, either version 3 of the License, or (at your option)
10 * Cleanflight and Betaflight are distributed in the hope that they
11 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this software.
18 * If not, see <http://www.gnu.org/licenses/>.
22 // CMS things for blackbox and flashfs.
32 #if defined(USE_CMS) && defined(USE_BLACKBOX)
34 #include "build/version.h"
36 #include "blackbox/blackbox.h"
37 #include "blackbox/blackbox_io.h"
40 #include "cms/cms_types.h"
41 #include "cms/cms_menu_blackbox.h"
43 #include "common/printf.h"
44 #include "common/utils.h"
46 #include "config/feature.h"
48 #include "drivers/flash.h"
49 #include "drivers/time.h"
50 #include "drivers/sdcard.h"
52 #include "fc/config.h"
54 #include "io/asyncfatfs/asyncfatfs.h"
55 #include "io/flashfs.h"
56 #include "io/beeper.h"
60 static const char * const cmsx_BlackboxDeviceNames
[] = {
67 static uint16_t blackboxConfig_p_ratio
;
69 static uint8_t cmsx_BlackboxDevice
;
70 static OSD_TAB_t cmsx_BlackboxDeviceTable
= { &cmsx_BlackboxDevice
, 2, cmsx_BlackboxDeviceNames
};
72 #define CMS_BLACKBOX_STRING_LENGTH 8
73 static char cmsx_BlackboxStatus
[CMS_BLACKBOX_STRING_LENGTH
];
74 static char cmsx_BlackboxDeviceStorageUsed
[CMS_BLACKBOX_STRING_LENGTH
];
75 static char cmsx_BlackboxDeviceStorageFree
[CMS_BLACKBOX_STRING_LENGTH
];
77 static void cmsx_Blackbox_GetDeviceStatus(void)
80 #if defined(USE_SDCARD) || defined(USE_FLASHFS)
81 bool storageDeviceIsWorking
= false;
83 uint32_t storageUsed
= 0;
84 uint32_t storageFree
= 0;
86 switch (blackboxConfig()->device
)
89 case BLACKBOX_DEVICE_SDCARD
:
92 if (!sdcard_isInserted()) {
93 tfp_sprintf(cmsx_BlackboxStatus
, "NO CARD");
94 } else if (!sdcard_isFunctional()) {
95 tfp_sprintf(cmsx_BlackboxStatus
, "FAULT");
97 switch (afatfs_getFilesystemState()) {
98 case AFATFS_FILESYSTEM_STATE_READY
:
99 tfp_sprintf(cmsx_BlackboxStatus
, "READY");
100 storageDeviceIsWorking
= true;
102 case AFATFS_FILESYSTEM_STATE_INITIALIZATION
:
103 tfp_sprintf(cmsx_BlackboxStatus
, "INIT");
105 case AFATFS_FILESYSTEM_STATE_FATAL
:
106 case AFATFS_FILESYSTEM_STATE_UNKNOWN
:
108 tfp_sprintf(cmsx_BlackboxStatus
, "FAULT");
113 if (storageDeviceIsWorking
) {
114 storageFree
= afatfs_getContiguousFreeSpace() / 1024000;
115 storageUsed
= (sdcard_getMetadata()->numBlocks
/ 2000) - storageFree
;
122 case BLACKBOX_DEVICE_FLASH
:
125 storageDeviceIsWorking
= flashfsIsSupported();
126 if (storageDeviceIsWorking
) {
127 tfp_sprintf(cmsx_BlackboxStatus
, "READY");
129 const flashGeometry_t
*geometry
= flashfsGetGeometry();
130 storageUsed
= flashfsGetOffset() / 1024;
131 storageFree
= (geometry
->totalSize
/ 1024) - storageUsed
;
133 tfp_sprintf(cmsx_BlackboxStatus
, "FAULT");
140 tfp_sprintf(cmsx_BlackboxStatus
, "---");
143 /* Storage counters */
144 tfp_sprintf(cmsx_BlackboxDeviceStorageUsed
, "%ld%s", storageUsed
, unit
);
145 tfp_sprintf(cmsx_BlackboxDeviceStorageFree
, "%ld%s", storageFree
, unit
);
149 static long cmsx_EraseFlash(displayPort_t
*pDisplay
, const void *ptr
)
153 if (!flashfsIsSupported()) {
157 displayClearScreen(pDisplay
);
158 displayWrite(pDisplay
, 5, 3, "ERASING FLASH...");
159 displayResync(pDisplay
); // Was max7456RefreshAll(); Why at this timing?
161 flashfsEraseCompletely();
162 while (!flashfsIsReady()) {
166 beeper(BEEPER_BLACKBOX_ERASE
);
167 displayClearScreen(pDisplay
);
168 displayResync(pDisplay
); // Was max7456RefreshAll(); wedges during heavy SPI?
170 // Update storage device status to show new used space amount
171 cmsx_Blackbox_GetDeviceStatus();
175 #endif // USE_FLASHFS
177 static long cmsx_Blackbox_onEnter(void)
179 cmsx_Blackbox_GetDeviceStatus();
180 cmsx_BlackboxDevice
= blackboxConfig()->device
;
182 blackboxConfig_p_ratio
= blackboxConfig()->p_ratio
;
186 static long cmsx_Blackbox_onExit(const OSD_Entry
*self
)
190 if (blackboxMayEditConfig()) {
191 blackboxConfigMutable()->device
= cmsx_BlackboxDevice
;
192 blackboxValidateConfig();
194 blackboxConfigMutable()->p_ratio
= blackboxConfig_p_ratio
;
198 static OSD_Entry cmsx_menuBlackboxEntries
[] =
200 { "-- BLACKBOX --", OME_Label
, NULL
, NULL
, 0},
201 { "DEVICE", OME_TAB
, NULL
, &cmsx_BlackboxDeviceTable
, 0 },
202 { "(STATUS)", OME_String
, NULL
, &cmsx_BlackboxStatus
, 0 },
203 { "(USED)", OME_String
, NULL
, &cmsx_BlackboxDeviceStorageUsed
, 0 },
204 { "(FREE)", OME_String
, NULL
, &cmsx_BlackboxDeviceStorageFree
, 0 },
205 { "P RATIO", OME_UINT16
, NULL
, &(OSD_UINT16_t
){ &blackboxConfig_p_ratio
, 1, INT16_MAX
, 1 },0 },
208 { "ERASE FLASH", OME_Funcall
, cmsx_EraseFlash
, NULL
, 0 },
209 #endif // USE_FLASHFS
211 { "BACK", OME_Back
, NULL
, NULL
, 0 },
212 { NULL
, OME_END
, NULL
, NULL
, 0 }
215 CMS_Menu cmsx_menuBlackbox
= {
216 #ifdef CMS_MENU_DEBUG
217 .GUARD_text
= "MENUBB",
218 .GUARD_type
= OME_MENU
,
220 .onEnter
= cmsx_Blackbox_onEnter
,
221 .onExit
= cmsx_Blackbox_onExit
,
222 .entries
= cmsx_menuBlackboxEntries