forked from xuos/xiuos
add embedded database lib (flashdb)
it is OK
This commit is contained in:
@@ -18,5 +18,5 @@ menu "Applications"
|
||||
source "$APP_DIR/Applications/control_app/Kconfig"
|
||||
source "$APP_DIR/Applications/knowing_app/Kconfig"
|
||||
source "$APP_DIR/Applications/sensor_app/Kconfig"
|
||||
|
||||
source "$APP_DIR/Applications/embedded_database_app/Kconfig"
|
||||
endmenu
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
menuconfig USING_EMBEDDED_DATABASE_APP
|
||||
bool "embedded database app"
|
||||
default n
|
||||
if USING_EMBEDDED_DATABASE_APP
|
||||
source "$APP_DIR/Applications/embedded_database_app/flashdb_app/Kconfig"
|
||||
endif
|
||||
@@ -0,0 +1,14 @@
|
||||
import os
|
||||
Import('RTT_ROOT')
|
||||
from building import *
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
objs = []
|
||||
list = os.listdir(cwd)
|
||||
|
||||
for d in list:
|
||||
path = os.path.join(cwd, d)
|
||||
if os.path.isfile(os.path.join(path, 'SConscript')):
|
||||
objs = objs + SConscript(os.path.join(path, 'SConscript'))
|
||||
|
||||
Return('objs')
|
||||
@@ -0,0 +1,5 @@
|
||||
config EMBEDDED_DATABASE_FLASHDB_APP
|
||||
bool "embedded database apps/flashdb(example)"
|
||||
select USING_EMBEDDED_DATABASE
|
||||
select USING_EMBEDDED_DATABASE_FLASHDB
|
||||
default n
|
||||
@@ -0,0 +1,9 @@
|
||||
from building import *
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
src = Glob('*.c') + Glob('*.cpp')
|
||||
CPPPATH = [cwd]
|
||||
|
||||
group = DefineGroup('flashdb(example)', src, depend = ['EMBEDDED_DATABASE_FLASHDB_APP'], LOCAL_CPPPATH = CPPPATH)
|
||||
|
||||
Return('group')
|
||||
@@ -0,0 +1,129 @@
|
||||
#include <transform.h>
|
||||
#include <flashdb.h>
|
||||
#define FDB_LOG_TAG "[flashdb_app]"
|
||||
static pthread_mutex_t kv_locker, ts_locker;
|
||||
static uint32_t boot_count = 0;
|
||||
static time_t boot_time[10] = {0, 1, 2, 3};
|
||||
/* default KV nodes */
|
||||
static struct fdb_default_kv_node default_kv_table[] = {
|
||||
{"username", "armink", 0}, /* string KV */
|
||||
{"password", "123456", 0}, /* string KV */
|
||||
{"boot_count", &boot_count, sizeof(boot_count)}, /* int type KV */
|
||||
{"boot_time", &boot_time, sizeof(boot_time)}, /* int array type KV */
|
||||
};
|
||||
/* KVDB object */
|
||||
static struct fdb_kvdb kvdb = { 0 };
|
||||
/* TSDB object */
|
||||
struct fdb_tsdb tsdb = { 0 };
|
||||
/* counts for simulated timestamp */
|
||||
static int counts = 0;
|
||||
|
||||
extern void kvdb_basic_sample(fdb_kvdb_t kvdb);
|
||||
extern void kvdb_type_string_sample(fdb_kvdb_t kvdb);
|
||||
extern void kvdb_type_blob_sample(fdb_kvdb_t kvdb);
|
||||
extern void tsdb_sample(fdb_tsdb_t tsdb);
|
||||
|
||||
static void lock(fdb_db_t db)
|
||||
{
|
||||
pthread_mutex_lock((pthread_mutex_t *)db->user_data);
|
||||
}
|
||||
|
||||
static void unlock(fdb_db_t db)
|
||||
{
|
||||
pthread_mutex_unlock((pthread_mutex_t *)db->user_data);
|
||||
}
|
||||
|
||||
static fdb_time_t get_time(void)
|
||||
{
|
||||
return time(NULL);
|
||||
}
|
||||
|
||||
int flashdb_app(void)
|
||||
{
|
||||
fdb_err_t result;
|
||||
bool file_mode = true;
|
||||
uint32_t sec_size = 4096, db_size = sec_size * 4;
|
||||
|
||||
#ifdef FDB_USING_KVDB
|
||||
{ /* KVDB Sample */
|
||||
struct fdb_default_kv default_kv;
|
||||
|
||||
default_kv.kvs = default_kv_table;
|
||||
default_kv.num = sizeof(default_kv_table) / sizeof(default_kv_table[0]);
|
||||
/* set the lock and unlock function if you want */
|
||||
pthread_mutex_init(&kv_locker, NULL);
|
||||
fdb_kvdb_control(&kvdb, FDB_KVDB_CTRL_SET_LOCK, (void *)lock);
|
||||
fdb_kvdb_control(&kvdb, FDB_KVDB_CTRL_SET_UNLOCK, (void *)unlock);
|
||||
/* set the sector and database max size */
|
||||
fdb_kvdb_control(&kvdb, FDB_KVDB_CTRL_SET_SEC_SIZE, &sec_size);
|
||||
fdb_kvdb_control(&kvdb, FDB_KVDB_CTRL_SET_MAX_SIZE, &db_size);
|
||||
/* enable file mode */
|
||||
fdb_kvdb_control(&kvdb, FDB_KVDB_CTRL_SET_FILE_MODE, &file_mode);
|
||||
/* create database directory */
|
||||
mkdir("fdb_kvdb1", 0777);
|
||||
/* Key-Value database initialization
|
||||
*
|
||||
* &kvdb: database object
|
||||
* "env": database name
|
||||
* "fdb_kvdb1": The flash partition name base on FAL. Please make sure it's in FAL partition table.
|
||||
* Please change to YOUR partition name.
|
||||
* &default_kv: The default KV nodes. It will auto add to KVDB when first initialize successfully.
|
||||
* &kv_locker: The locker object.
|
||||
*/
|
||||
result = fdb_kvdb_init(&kvdb, "env", "fdb_kvdb1", &default_kv, &kv_locker);
|
||||
|
||||
if (result != FDB_NO_ERR) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* run basic KV samples */
|
||||
kvdb_basic_sample(&kvdb);
|
||||
/* run string KV samples */
|
||||
kvdb_type_string_sample(&kvdb);
|
||||
/* run blob KV samples */
|
||||
kvdb_type_blob_sample(&kvdb);
|
||||
}
|
||||
#endif /* FDB_USING_KVDB */
|
||||
|
||||
#ifdef FDB_USING_TSDB
|
||||
{ /* TSDB Sample */
|
||||
/* set the lock and unlock function if you want */
|
||||
pthread_mutex_init(&ts_locker, NULL);
|
||||
fdb_tsdb_control(&tsdb, FDB_TSDB_CTRL_SET_LOCK, (void *)lock);
|
||||
fdb_tsdb_control(&tsdb, FDB_TSDB_CTRL_SET_UNLOCK, (void *)unlock);
|
||||
/* set the sector and database max size */
|
||||
fdb_tsdb_control(&tsdb, FDB_TSDB_CTRL_SET_SEC_SIZE, &sec_size);
|
||||
fdb_tsdb_control(&tsdb, FDB_TSDB_CTRL_SET_MAX_SIZE, &db_size);
|
||||
/* enable file mode */
|
||||
fdb_tsdb_control(&tsdb, FDB_TSDB_CTRL_SET_FILE_MODE, &file_mode);
|
||||
/* create database directory */
|
||||
mkdir("fdb_tsdb1", 0777);
|
||||
/* Time series database initialization
|
||||
*
|
||||
* &tsdb: database object
|
||||
* "log": database name
|
||||
* "fdb_tsdb1": The flash partition name base on FAL. Please make sure it's in FAL partition table.
|
||||
* Please change to YOUR partition name.
|
||||
* get_time: The get current timestamp function.
|
||||
* 128: maximum length of each log
|
||||
* ts_locker: The locker object.
|
||||
*/
|
||||
result = fdb_tsdb_init(&tsdb, "log", "fdb_tsdb1", get_time, 128, &ts_locker);
|
||||
/* read last saved time for simulated timestamp */
|
||||
fdb_tsdb_control(&tsdb, FDB_TSDB_CTRL_GET_LAST_TIME, &counts);
|
||||
|
||||
if (result != FDB_NO_ERR) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* run TSDB sample */
|
||||
tsdb_sample(&tsdb);
|
||||
}
|
||||
#endif /* FDB_USING_TSDB */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef __RT_THREAD_H__
|
||||
MSH_CMD_EXPORT(flashdb_app, flashdb test);
|
||||
#endif
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Armink, <armink.ztl@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief basic KV samples.
|
||||
*
|
||||
* basic Key-Value Database KV feature samples
|
||||
* get and show currnet boot counts
|
||||
*/
|
||||
|
||||
#include <flashdb.h>
|
||||
|
||||
#ifdef FDB_USING_KVDB
|
||||
|
||||
#define FDB_LOG_TAG "[sample][kvdb][basic]"
|
||||
|
||||
void kvdb_basic_sample(fdb_kvdb_t kvdb)
|
||||
{
|
||||
struct fdb_blob blob;
|
||||
int boot_count = 0;
|
||||
|
||||
FDB_INFO("==================== kvdb_basic_sample ====================\n");
|
||||
|
||||
{ /* GET the KV value */
|
||||
/* get the "boot_count" KV value */
|
||||
fdb_kv_get_blob(kvdb, "boot_count", fdb_blob_make(&blob, &boot_count, sizeof(boot_count)));
|
||||
/* the blob.saved.len is more than 0 when get the value successful */
|
||||
if (blob.saved.len > 0) {
|
||||
FDB_INFO("get the 'boot_count' value is %d\n", boot_count);
|
||||
} else {
|
||||
FDB_INFO("get the 'boot_count' failed\n");
|
||||
}
|
||||
}
|
||||
|
||||
{ /* CHANGE the KV value */
|
||||
/* increase the boot count */
|
||||
boot_count ++;
|
||||
/* change the "boot_count" KV's value */
|
||||
fdb_kv_set_blob(kvdb, "boot_count", fdb_blob_make(&blob, &boot_count, sizeof(boot_count)));
|
||||
FDB_INFO("set the 'boot_count' value to %d\n", boot_count);
|
||||
}
|
||||
|
||||
FDB_INFO("===========================================================\n");
|
||||
}
|
||||
|
||||
#endif /* FDB_USING_KVDB */
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Armink, <armink.ztl@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief blob KV samples.
|
||||
*
|
||||
* Key-Value Database blob type KV feature samples
|
||||
*/
|
||||
|
||||
#include <flashdb.h>
|
||||
|
||||
#ifdef FDB_USING_KVDB
|
||||
|
||||
#define FDB_LOG_TAG "[sample][kvdb][blob]"
|
||||
|
||||
void kvdb_type_blob_sample(fdb_kvdb_t kvdb)
|
||||
{
|
||||
struct fdb_blob blob;
|
||||
|
||||
FDB_INFO("==================== kvdb_type_blob_sample ====================\n");
|
||||
|
||||
{ /* CREATE new Key-Value */
|
||||
int temp_data = 36;
|
||||
|
||||
/* It will create new KV node when "temp" KV not in database.
|
||||
* fdb_blob_make: It's a blob make function, and it will return the blob when make finish.
|
||||
*/
|
||||
fdb_kv_set_blob(kvdb, "temp", fdb_blob_make(&blob, &temp_data, sizeof(temp_data)));
|
||||
FDB_INFO("create the 'temp' blob KV, value is: %d\n", temp_data);
|
||||
}
|
||||
|
||||
{ /* GET the KV value */
|
||||
int temp_data = 0;
|
||||
|
||||
/* get the "temp" KV value */
|
||||
fdb_kv_get_blob(kvdb, "temp", fdb_blob_make(&blob, &temp_data, sizeof(temp_data)));
|
||||
/* the blob.saved.len is more than 0 when get the value successful */
|
||||
if (blob.saved.len > 0) {
|
||||
FDB_INFO("get the 'temp' value is: %d\n", temp_data);
|
||||
}
|
||||
}
|
||||
|
||||
{ /* CHANGE the KV value */
|
||||
int temp_data = 38;
|
||||
|
||||
/* change the "temp" KV's value to 38 */
|
||||
fdb_kv_set_blob(kvdb, "temp", fdb_blob_make(&blob, &temp_data, sizeof(temp_data)));
|
||||
FDB_INFO("set 'temp' value to %d\n", temp_data);
|
||||
}
|
||||
|
||||
{ /* DELETE the KV by name */
|
||||
fdb_kv_del(kvdb, "temp");
|
||||
FDB_INFO("delete the 'temp' finish\n");
|
||||
}
|
||||
|
||||
FDB_INFO("===========================================================\n");
|
||||
}
|
||||
|
||||
#endif /* FDB_USING_KVDB */
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Armink, <armink.ztl@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief string KV samples.
|
||||
*
|
||||
* Key-Value Database string type KV feature samples source file.
|
||||
*/
|
||||
|
||||
#include <flashdb.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef FDB_USING_KVDB
|
||||
|
||||
#define FDB_LOG_TAG "[sample][kvdb][string]"
|
||||
|
||||
void kvdb_type_string_sample(fdb_kvdb_t kvdb)
|
||||
{
|
||||
FDB_INFO("==================== kvdb_type_string_sample ====================\n");
|
||||
|
||||
{ /* CREATE new Key-Value */
|
||||
char temp_data[10] = "36C";
|
||||
|
||||
/* It will create new KV node when "temp" KV not in database. */
|
||||
fdb_kv_set(kvdb, "temp", temp_data);
|
||||
FDB_INFO("create the 'temp' string KV, value is: %s\n", temp_data);
|
||||
}
|
||||
|
||||
{ /* GET the KV value */
|
||||
char *return_value, temp_data[10] = { 0 };
|
||||
|
||||
/* Get the "temp" KV value.
|
||||
* NOTE: The return value saved in fdb_kv_get's buffer. Please copy away as soon as possible.
|
||||
*/
|
||||
return_value = fdb_kv_get(kvdb, "temp");
|
||||
/* the return value is NULL when get the value failed */
|
||||
if (return_value != NULL) {
|
||||
strncpy(temp_data, return_value, sizeof(temp_data));
|
||||
FDB_INFO("get the 'temp' value is: %s\n", temp_data);
|
||||
}
|
||||
}
|
||||
|
||||
{ /* CHANGE the KV value */
|
||||
char temp_data[10] = "38C";
|
||||
|
||||
/* change the "temp" KV's value to "38.1" */
|
||||
fdb_kv_set(kvdb, "temp", temp_data);
|
||||
FDB_INFO("set 'temp' value to %s\n", temp_data);
|
||||
}
|
||||
|
||||
{ /* DELETE the KV by name */
|
||||
fdb_kv_del(kvdb, "temp");
|
||||
FDB_INFO("delete the 'temp' finish\n");
|
||||
}
|
||||
|
||||
FDB_INFO("===========================================================\n");
|
||||
}
|
||||
|
||||
#endif /* FDB_USING_KVDB */
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Armink, <armink.ztl@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief TSDB samples.
|
||||
*
|
||||
* Time series log (like TSDB) feature samples source file.
|
||||
*
|
||||
* TSL is time series log, the TSDB saved many TSLs.
|
||||
*/
|
||||
|
||||
#include <flashdb.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef FDB_USING_TSDB
|
||||
|
||||
#define FDB_LOG_TAG "[sample][tsdb]"
|
||||
|
||||
struct env_status {
|
||||
int temp;
|
||||
int humi;
|
||||
};
|
||||
|
||||
static bool query_cb(fdb_tsl_t tsl, void *arg);
|
||||
static bool query_by_time_cb(fdb_tsl_t tsl, void *arg);
|
||||
static bool set_status_cb(fdb_tsl_t tsl, void *arg);
|
||||
|
||||
void tsdb_sample(fdb_tsdb_t tsdb)
|
||||
{
|
||||
struct fdb_blob blob;
|
||||
|
||||
FDB_INFO("==================== tsdb_sample ====================\n");
|
||||
|
||||
{ /* APPEND new TSL (time series log) */
|
||||
struct env_status status;
|
||||
|
||||
/* append new log to TSDB */
|
||||
status.temp = 36;
|
||||
status.humi = 85;
|
||||
fdb_tsl_append(tsdb, fdb_blob_make(&blob, &status, sizeof(status)));
|
||||
FDB_INFO("append the new status.temp (%d) and status.humi (%d)\n", status.temp, status.humi);
|
||||
|
||||
status.temp = 38;
|
||||
status.humi = 90;
|
||||
fdb_tsl_append(tsdb, fdb_blob_make(&blob, &status, sizeof(status)));
|
||||
FDB_INFO("append the new status.temp (%d) and status.humi (%d)\n", status.temp, status.humi);
|
||||
}
|
||||
|
||||
{ /* QUERY the TSDB */
|
||||
/* query all TSL in TSDB by iterator */
|
||||
fdb_tsl_iter(tsdb, query_cb, tsdb);
|
||||
}
|
||||
|
||||
{ /* QUERY the TSDB by time */
|
||||
/* prepare query time (from 1970-01-01 00:00:00 to 2020-05-05 00:00:00) */
|
||||
struct tm tm_from = { .tm_year = 1970 - 1900, .tm_mon = 0, .tm_mday = 1, .tm_hour = 0, .tm_min = 0, .tm_sec = 0 };
|
||||
struct tm tm_to = { .tm_year = 2020 - 1900, .tm_mon = 4, .tm_mday = 5, .tm_hour = 0, .tm_min = 0, .tm_sec = 0 };
|
||||
time_t from_time = mktime(&tm_from), to_time = mktime(&tm_to);
|
||||
size_t count;
|
||||
/* query all TSL in TSDB by time */
|
||||
fdb_tsl_iter_by_time(tsdb, from_time, to_time, query_by_time_cb, tsdb);
|
||||
/* query all FDB_TSL_WRITE status TSL's count in TSDB by time */
|
||||
count = fdb_tsl_query_count(tsdb, from_time, to_time, FDB_TSL_WRITE);
|
||||
FDB_INFO("query count is: %zu\n", count);
|
||||
}
|
||||
|
||||
{ /* SET the TSL status */
|
||||
/* Change the TSL status by iterator or time iterator
|
||||
* set_status_cb: the change operation will in this callback
|
||||
*
|
||||
* NOTE: The actions to modify the state must be in order.
|
||||
* like: FDB_TSL_WRITE -> FDB_TSL_USER_STATUS1 -> FDB_TSL_DELETED -> FDB_TSL_USER_STATUS2
|
||||
* The intermediate states can also be ignored.
|
||||
* such as: FDB_TSL_WRITE -> FDB_TSL_DELETED
|
||||
*/
|
||||
fdb_tsl_iter(tsdb, set_status_cb, tsdb);
|
||||
}
|
||||
|
||||
FDB_INFO("===========================================================\n");
|
||||
}
|
||||
|
||||
static bool query_cb(fdb_tsl_t tsl, void *arg)
|
||||
{
|
||||
struct fdb_blob blob;
|
||||
struct env_status status;
|
||||
fdb_tsdb_t db = arg;
|
||||
|
||||
fdb_blob_read((fdb_db_t) db, fdb_tsl_to_blob(tsl, fdb_blob_make(&blob, &status, sizeof(status))));
|
||||
FDB_INFO("[query_cb] queried a TSL: time: %ld, temp: %d, humi: %d\n", tsl->time, status.temp, status.humi);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool query_by_time_cb(fdb_tsl_t tsl, void *arg)
|
||||
{
|
||||
struct fdb_blob blob;
|
||||
struct env_status status;
|
||||
fdb_tsdb_t db = arg;
|
||||
|
||||
fdb_blob_read((fdb_db_t) db, fdb_tsl_to_blob(tsl, fdb_blob_make(&blob, &status, sizeof(status))));
|
||||
FDB_INFO("[query_by_time_cb] queried a TSL: time: %ld, temp: %d, humi: %d\n", tsl->time, status.temp, status.humi);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool set_status_cb(fdb_tsl_t tsl, void *arg)
|
||||
{
|
||||
fdb_tsdb_t db = arg;
|
||||
|
||||
FDB_INFO("set the TSL (time %ld) status from %d to %d\n", tsl->time, tsl->status, FDB_TSL_USER_STATUS1);
|
||||
fdb_tsl_set_status(db, tsl, FDB_TSL_USER_STATUS1);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif /* FDB_USING_TSDB */
|
||||
@@ -11,6 +11,11 @@ menuconfig USING_CMSIS_5_DEMOAPP
|
||||
select IMAGE_PROCESSING_USING_TJPGD
|
||||
default n
|
||||
|
||||
config USING_CMSIS_5_NN_DEMOAPP_VEG_CLASSIFY
|
||||
bool "Using CMSIS-5 NN demo app vegetable classify"
|
||||
select USING_IMAGE_PROCESSING
|
||||
select IMAGE_PROCESSING_USING_TJPGD
|
||||
default n
|
||||
endif
|
||||
|
||||
|
||||
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
# CMSIS-NN vegetable classify example
|
||||
|
||||
This example uses CMSIS-NN to classify vegetable in real time under certain circumstances .
|
||||
|
||||
## Requirements:
|
||||
- CMSIS-NN in Framework/knowing/cmsis_5
|
||||
- **ov2640 need to be configured** in menuconfig "More Drivers->ov2640 driver" as follows
|
||||
- Output format (RGB565 mode)
|
||||
- (256) X direction resolution of outputimage
|
||||
- (256) Y direction resolution of outputimage
|
||||
- (512) X direction WINDOWS SIZE
|
||||
- (512) Y direction WINDOWS SIZE
|
||||
|
||||
## To run this demo:
|
||||
- Set up and configure the corresponding hardware environment.
|
||||
|
||||
- Run demo by type the command
|
||||
```
|
||||
cmsisnn_vegetable_classify
|
||||
|
||||
## Results
|
||||
|
||||
- **tomato**
|
||||
|
||||

|
||||
|
||||
- **potato**
|
||||
|
||||

|
||||
|
||||
- **pepper**
|
||||
|
||||

|
||||
|
||||
- **mushroom**
|
||||
|
||||

|
||||
+18
@@ -0,0 +1,18 @@
|
||||
from building import *
|
||||
import os
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
|
||||
src = Split('''
|
||||
model/nn_vegetable_classify.c
|
||||
cmsisnn_vegetable_classify.c
|
||||
''')
|
||||
|
||||
path = [
|
||||
cwd + '/model',
|
||||
cwd + '/demo'
|
||||
]
|
||||
|
||||
group = DefineGroup('CMSISNN vegetable classify application', src, depend = ['USING_CMSIS_5_NN_DEMOAPP_VEG_CLASSIFY'], CPPPATH = path)
|
||||
|
||||
Return('group')
|
||||
+188
@@ -0,0 +1,188 @@
|
||||
#include <rtthread.h>
|
||||
#include <rtdevice.h>
|
||||
#include "stdio.h"
|
||||
#include "string.h"
|
||||
|
||||
#ifdef OV2640_RGB565_MODE
|
||||
#ifdef RT_USING_POSIX
|
||||
#include <dfs_posix.h>
|
||||
#include <dfs_poll.h>
|
||||
#ifdef RT_USING_POSIX_TERMIOS
|
||||
#include <posix_termios.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <drv_ov2640.h>
|
||||
#include <drv_lcd.h>
|
||||
#include "nn_vegetable_classify.h"
|
||||
#define JPEG_BUF_SIZE (2 * OV2640_X_RESOLUTION_IMAGE_OUTSIZE * OV2640_Y_RESOLUTION_IMAGE_OUTSIZE)
|
||||
#define IOCTL_ERROR 1
|
||||
|
||||
static int fd = 0;
|
||||
static int infer_times = 0;
|
||||
static int photo_times = 0;
|
||||
static int height = OV2640_X_RESOLUTION_IMAGE_OUTSIZE;
|
||||
static int width = OV2640_Y_RESOLUTION_IMAGE_OUTSIZE;
|
||||
static _ioctl_shoot_para shoot_para_t = {0};
|
||||
const char *vegetable_label[] = {"mushroom", "pepper", "potato", "tomato"};
|
||||
|
||||
uint8_t *resized_buffer = NULL;
|
||||
uint8_t *in_buffer = NULL;
|
||||
|
||||
int get_top_prediction_detection(q7_t *predictions)
|
||||
{
|
||||
int max_ind = 0;
|
||||
int max_val = -128;
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
if (max_val < predictions[i])
|
||||
{
|
||||
max_val = predictions[i];
|
||||
max_ind = i;
|
||||
}
|
||||
}
|
||||
return max_ind;
|
||||
}
|
||||
|
||||
int cmsisnn_inference_vegetable_classify(uint8_t *input_data)
|
||||
{
|
||||
int8_t output_data[4];
|
||||
char output[50] = {0};
|
||||
char outputPrediction[50] = {0};
|
||||
memset(output, 0, 50);
|
||||
memset(outputPrediction, 0, 50);
|
||||
|
||||
run_nn_sn_classify((int8_t *)input_data, output_data);
|
||||
arm_softmax_q7(output_data, 4, output_data);
|
||||
|
||||
infer_times++;
|
||||
int top_ind = get_top_prediction_detection(output_data);
|
||||
printf("times:%d Prediction:%s \r\n", infer_times, vegetable_label[top_ind]);
|
||||
sprintf(outputPrediction, "times:%d Prediction:%s \r\n", infer_times, vegetable_label[top_ind]);
|
||||
lcd_show_string(1, 280, 240, 16, 16, outputPrediction, RED);
|
||||
return top_ind;
|
||||
}
|
||||
|
||||
void resize_rgb888in_rgb565out(uint8_t *camera_image, uint16_t *resize_image)
|
||||
{
|
||||
uint8_t *psrc_temp = (uint8_t *)camera_image;
|
||||
uint16_t *pdst_temp = (uint16_t *)resize_image;
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
*pdst_temp++ = (*psrc_temp++ & 0xF8) << 8 | (*psrc_temp++ & 0xFC) << 3 | *psrc_temp++ >> 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void resize_rgb565in_rgb888out(uint8_t *camera_image, uint8_t *resize_image)
|
||||
{
|
||||
uint8_t *psrc_temp = (uint8_t *)camera_image;
|
||||
uint8_t *pdst_temp = (uint8_t *)resize_image;
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
uint8_t pixel_lo = *psrc_temp++;
|
||||
uint8_t pixel_hi = *psrc_temp++;
|
||||
*pdst_temp++ = (0xF8 & pixel_hi);
|
||||
*pdst_temp++ = ((0x07 & pixel_hi) << 5) | ((0xE0 & pixel_lo) >> 3);
|
||||
*pdst_temp++ = (0x1F & pixel_lo) << 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void lcd_show_ov2640_thread_detection(uint8_t *rgbbuffer)
|
||||
{
|
||||
int32_t ret = 0;
|
||||
while (1)
|
||||
{
|
||||
ret = ioctl(fd, IOCTRL_CAMERA_START_SHOT, &shoot_para_t);
|
||||
if (ret == IOCTL_ERROR)
|
||||
{
|
||||
printf("ov2640 can't wait event flag");
|
||||
free(rgbbuffer);
|
||||
return;
|
||||
}
|
||||
lcd_fill_array(0, 0, OV2640_X_RESOLUTION_IMAGE_OUTSIZE, OV2640_Y_RESOLUTION_IMAGE_OUTSIZE, rgbbuffer);
|
||||
|
||||
if (photo_times % 20 == 0)
|
||||
{
|
||||
resize_rgb565in_rgb888out(rgbbuffer, resized_buffer);
|
||||
int pixel = 0;
|
||||
for (int i = 0; i < 3 * width; i += 3 * width / CONV1_IN_DIM)
|
||||
{
|
||||
for (int j = 0; j < 3 * height; j += 3 * height / CONV1_IN_DIM)
|
||||
{
|
||||
for (int k = 0; k < 3; k++, pixel++)
|
||||
{
|
||||
*(in_buffer + pixel) = *(resized_buffer + 256 * i + j + k);
|
||||
}
|
||||
}
|
||||
}
|
||||
cmsisnn_inference_vegetable_classify(in_buffer);
|
||||
}
|
||||
photo_times++;
|
||||
}
|
||||
}
|
||||
|
||||
void cmsisnn_vegetable_classify()
|
||||
{
|
||||
fd = open("/dev/ov2640", O_RDONLY);
|
||||
if (fd < 0)
|
||||
{
|
||||
printf("open ov2640 fail !!");
|
||||
return;
|
||||
}
|
||||
printf("memory_init \n\r");
|
||||
uint8_t *JpegBuffer = malloc(JPEG_BUF_SIZE);
|
||||
if (JpegBuffer == NULL)
|
||||
{
|
||||
printf("JpegBuffer senddata buf malloc error!\n");
|
||||
return;
|
||||
}
|
||||
resized_buffer = malloc(3 * width * height);
|
||||
if (resized_buffer == NULL)
|
||||
{
|
||||
printf("Resized_buffer buf malloc error!\n");
|
||||
return;
|
||||
}
|
||||
in_buffer = malloc(CONV1_IN_CH * CONV1_IN_DIM * CONV1_IN_DIM);
|
||||
if (in_buffer == NULL)
|
||||
{
|
||||
printf("In_buffer buf malloc error!\n");
|
||||
return;
|
||||
}
|
||||
memory_init();
|
||||
printf("memory_init success\n\r");
|
||||
|
||||
shoot_para_t.pdata = (uint32_t)JpegBuffer;
|
||||
shoot_para_t.length = JPEG_BUF_SIZE / 2;
|
||||
|
||||
int result = 0;
|
||||
pthread_t tid = 0;
|
||||
pthread_attr_t attr;
|
||||
struct sched_param prio;
|
||||
prio.sched_priority = 8;
|
||||
size_t stack_size = 1024 * 11;
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setschedparam(&attr, &prio);
|
||||
pthread_attr_setstacksize(&attr, stack_size);
|
||||
|
||||
result = pthread_create(&tid, &attr, lcd_show_ov2640_thread_detection, JpegBuffer);
|
||||
if (0 == result) {
|
||||
printf("thread_detect_entry successfully!\n");
|
||||
} else {
|
||||
printf("thread_detect_entry failed! error code is %d.\n", result);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef __RT_THREAD_H__
|
||||
MSH_CMD_EXPORT(cmsisnn_vegetable_classify, classify vegetable using cmsis-nn);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
BIN
Binary file not shown.
|
After Width: | Height: | Size: 144 KiB |
BIN
Binary file not shown.
|
After Width: | Height: | Size: 140 KiB |
BIN
Binary file not shown.
|
After Width: | Height: | Size: 126 KiB |
BIN
Binary file not shown.
|
After Width: | Height: | Size: 141 KiB |
+108
@@ -0,0 +1,108 @@
|
||||
#include "nn_vegetable_classify.h"
|
||||
|
||||
static const q7_t conv1_w[CONV1_WT_SHAPE] = CONV1_WT;
|
||||
static const q7_t conv1_b[CONV1_BIAS_SHAPE] = CONV1_BIAS;
|
||||
static const q7_t conv2_w[CONV2_WT_SHAPE] = CONV2_WT;
|
||||
static const q7_t conv2_b[CONV2_BIAS_SHAPE] = CONV2_BIAS;
|
||||
// static const q7_t conv3_w[CONV3_WT_SHAPE] = CONV3_WT;
|
||||
// static const q7_t conv3_b[CONV3_BIAS_SHAPE] = CONV3_BIAS;
|
||||
static const q7_t interface_w[INTERFACE_WT_SHAPE] = INTERFACE_WT;
|
||||
static const q7_t interface_b[INTERFACE_BIAS_SHAPE] = INTERFACE_BIAS;
|
||||
static const q7_t linear_w[LINEAR_WT_SHAPE] = LINEAR_WT;
|
||||
static const q7_t linear_b[LINEAR_BIAS_SHAPE] = LINEAR_BIAS;
|
||||
|
||||
q7_t *conv1_out = NULL;
|
||||
q7_t *pool1_out = NULL;
|
||||
q7_t *conv2_out = NULL;
|
||||
q7_t *pool2_out = NULL;
|
||||
// q7_t *conv3_out = NULL ;
|
||||
q7_t *interface_out = NULL;
|
||||
q7_t *linear_out = NULL;
|
||||
q7_t *y_out = NULL;
|
||||
q7_t *conv_buffer = NULL;
|
||||
q7_t *fc_buffer = NULL;
|
||||
|
||||
void memory_init()
|
||||
{
|
||||
static int flag = 0;
|
||||
if (flag == 0)
|
||||
{
|
||||
conv1_out = malloc(CONV1_OUT_CH * CONV1_OUT_DIM * CONV1_OUT_DIM);
|
||||
if (conv1_out == NULL)
|
||||
{
|
||||
printf("conv1_out malloc failed...\n");
|
||||
return;
|
||||
}
|
||||
pool1_out = malloc(CONV1_OUT_CH * POOL1_OUT_DIM * POOL1_OUT_DIM);
|
||||
if (pool1_out == NULL)
|
||||
{
|
||||
printf("pool1_out malloc failed...\n");
|
||||
return;
|
||||
}
|
||||
conv2_out = malloc(CONV2_OUT_CH * CONV2_OUT_DIM * CONV2_OUT_DIM);
|
||||
if (conv2_out == NULL)
|
||||
{
|
||||
printf("conv2_out malloc failed...\n");
|
||||
return;
|
||||
}
|
||||
pool2_out = malloc(CONV2_OUT_CH * POOL2_OUT_DIM * POOL2_OUT_DIM);
|
||||
if (pool2_out == NULL)
|
||||
{
|
||||
printf("pool2_out malloc failed...\n");
|
||||
return;
|
||||
}
|
||||
interface_out = malloc(INTERFACE_OUT_DIM);
|
||||
if (interface_out == NULL)
|
||||
{
|
||||
printf("interface_out malloc failed...\n");
|
||||
return;
|
||||
}
|
||||
linear_out = malloc(LINEAR_OUT_DIM);
|
||||
if (linear_out == NULL)
|
||||
{
|
||||
printf("linear_out malloc failed...\n");
|
||||
return;
|
||||
}
|
||||
y_out = malloc(LINEAR_OUT_DIM);
|
||||
if (y_out == NULL)
|
||||
{
|
||||
printf("y_out malloc failed...\n");
|
||||
return;
|
||||
}
|
||||
conv_buffer = malloc(MAX_CONV_BUFFER_SIZE);
|
||||
if (conv_buffer == NULL)
|
||||
{
|
||||
printf("conv_buffer malloc failed...\n");
|
||||
return;
|
||||
}
|
||||
fc_buffer = malloc(MAX_FC_BUFFER);
|
||||
if (fc_buffer == NULL)
|
||||
{
|
||||
printf("fc_buffer malloc failed...\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void run_nn_sn_classify(q7_t *input_data, q7_t *output_data)
|
||||
{
|
||||
for (int i = 0; i < CONV1_IN_CH * CONV1_IN_DIM * CONV1_IN_DIM; i++)
|
||||
{
|
||||
input_data[i] = input_data[i] - 127;
|
||||
}
|
||||
arm_convolve_HWC_q7_basic(input_data, CONV1_IN_DIM, CONV1_IN_CH, conv1_w, CONV1_OUT_CH, CONV1_KER_DIM, CONV1_PAD, CONV1_STRIDE, conv1_b, CONV1_BIAS_LSHIFT, CONV1_OUT_RSHIFT, conv1_out, CONV1_OUT_DIM, (q15_t *)conv_buffer, fc_buffer);
|
||||
arm_maxpool_q7_HWC(conv1_out, POOL1_IN_DIM, POOL1_IN_CH, POOL1_KER_DIM, POOL1_PAD, POOL1_STRIDE, POOL1_OUT_DIM, NULL, pool1_out);
|
||||
arm_relu_q7(pool1_out, POOL1_OUT_DIM * POOL1_OUT_DIM * CONV1_OUT_CH);
|
||||
arm_convolve_HWC_q7_basic(pool1_out, CONV2_IN_DIM, CONV2_IN_CH, conv2_w, CONV2_OUT_CH, CONV2_KER_DIM, CONV2_PAD, CONV2_STRIDE, conv2_b, CONV2_BIAS_LSHIFT, CONV2_OUT_RSHIFT, conv2_out, CONV2_OUT_DIM, (q15_t *)conv_buffer, NULL);
|
||||
arm_maxpool_q7_HWC(conv2_out, POOL2_IN_DIM, POOL2_IN_CH, POOL2_KER_DIM, POOL2_PAD, POOL2_STRIDE, POOL2_OUT_DIM, NULL, pool2_out);
|
||||
arm_relu_q7(pool2_out, POOL2_OUT_DIM * POOL2_OUT_DIM * CONV2_OUT_CH);
|
||||
// printf("1\n");
|
||||
// arm_convolve_HWC_q7_basic(pool2_out, CONV3_IN_DIM, CONV3_IN_CH, conv3_w, CONV3_OUT_CH, CONV3_KER_DIM,
|
||||
// CONV3_PAD, CONV3_STRIDE, conv3_b, CONV3_BIAS_LSHIFT, CONV3_OUT_RSHIFT, conv3_out,
|
||||
// CONV3_OUT_DIM, (q15_t *) conv_buffer, NULL);
|
||||
// arm_relu_q7(conv3_out, CONV3_OUT_DIM * CONV3_OUT_DIM * CONV3_OUT_CH);
|
||||
// printf("2\n");
|
||||
arm_fully_connected_q7_opt(pool2_out, interface_w, INTERFACE_IN_DIM, INTERFACE_OUT_DIM, INTERFACE_BIAS_LSHIFT, INTERFACE_OUT_RSHIFT, interface_b, interface_out, (q15_t *)fc_buffer);
|
||||
arm_relu_q7(interface_out, INTERFACE_OUT_DIM);
|
||||
arm_fully_connected_q7_opt(interface_out, linear_w, LINEAR_IN_DIM, LINEAR_OUT_DIM, LINEAR_BIAS_LSHIFT, LINEAR_OUT_RSHIFT, linear_b, output_data, (q15_t *)fc_buffer);
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
#ifndef __NN_H__
|
||||
#define __NN_H__
|
||||
|
||||
#include <transform.h>
|
||||
#include "arm_math.h"
|
||||
#include "arm_nnfunctions.h"
|
||||
#include "parameter_vegetable_classify.h"
|
||||
#include "weights_vegetable_classify.h"
|
||||
|
||||
void run_nn_detection(q7_t* input_data, q7_t* output_data);
|
||||
void memory_init();
|
||||
|
||||
#endif
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
#define CONV1_IN_CH 3
|
||||
#define CONV1_OUT_CH 32
|
||||
#define CONV1_KER_DIM 3
|
||||
#define CONV1_PAD 0
|
||||
#define CONV1_STRIDE 1
|
||||
#define CONV1_IN_DIM 32
|
||||
#define CONV1_OUT_DIM 30
|
||||
#define MAX_CONV_BUFFER_SIZE 3096
|
||||
#define POOL1_IN_CH 32
|
||||
#define POOL1_KER_DIM 2
|
||||
#define POOL1_PAD 0
|
||||
#define POOL1_STRIDE 2
|
||||
#define POOL1_IN_DIM 30
|
||||
#define POOL1_OUT_DIM 15
|
||||
#define CONV2_IN_CH 32
|
||||
#define CONV2_OUT_CH 32
|
||||
#define CONV2_KER_DIM 3
|
||||
#define CONV2_PAD 0
|
||||
#define CONV2_STRIDE 1
|
||||
#define CONV2_IN_DIM 15
|
||||
#define CONV2_OUT_DIM 13
|
||||
#define POOL2_IN_CH 32
|
||||
#define POOL2_KER_DIM 2
|
||||
#define POOL2_PAD 0
|
||||
#define POOL2_STRIDE 2
|
||||
#define POOL2_IN_DIM 13
|
||||
#define POOL2_OUT_DIM 6
|
||||
#define INTERFACE_OUT_DIM 32
|
||||
#define INTERFACE_IN_DIM 1152
|
||||
#define MAX_FC_BUFFER 3096
|
||||
#define LINEAR_OUT_DIM 4
|
||||
#define LINEAR_IN_DIM 32
|
||||
#define CONV1_BIAS_LSHIFT 6
|
||||
#define CONV1_OUT_RSHIFT 9
|
||||
#define CONV1_WEIGHT_Q 8
|
||||
#define CONV1_BIAS_Q 8
|
||||
#define CONV1_INPUT_Q 6
|
||||
#define CONV1_OUT_Q 5
|
||||
#define CONV2_BIAS_LSHIFT 4
|
||||
#define CONV2_OUT_RSHIFT 10
|
||||
#define CONV2_WEIGHT_Q 9
|
||||
#define CONV2_BIAS_Q 10
|
||||
#define CONV2_INPUT_Q 5
|
||||
#define CONV2_OUT_Q 4
|
||||
#define INTERFACE_BIAS_LSHIFT 3
|
||||
#define INTERFACE_OUT_RSHIFT 11
|
||||
#define INTERFACE_WEIGHT_Q 9
|
||||
#define INTERFACE_BIAS_Q 10
|
||||
#define INTERFACE_INPUT_Q 4
|
||||
#define INTERFACE_OUT_Q 2
|
||||
#define LINEAR_BIAS_LSHIFT 0
|
||||
#define LINEAR_OUT_RSHIFT 7
|
||||
#define LINEAR_WEIGHT_Q 7
|
||||
#define LINEAR_BIAS_Q 9
|
||||
#define LINEAR_INPUT_Q 2
|
||||
#define LINEAR_OUT_Q 2
|
||||
+16
File diff suppressed because one or more lines are too long
@@ -1,4 +1,5 @@
|
||||
config IMAGE_PROCESSING_TJPGDEC_APP
|
||||
bool "image processing apps/TJpgDec(example)"
|
||||
select USING_IMAGE_PROCESSING
|
||||
select IMAGE_PROCESSING_USING_TJPGD
|
||||
default n
|
||||
|
||||
Reference in New Issue
Block a user