pinebuds/apps/factory/app_factory.cpp

690 lines
18 KiB
C++

/***************************************************************************
*
* Copyright 2015-2019 BES.
* All rights reserved. All unpublished rights reserved.
*
* No part of this work may be used or reproduced in any form or by any
* means, or stored in a database or retrieval system, without prior written
* permission of BES.
*
* Use of this work is governed by a license granted by BES.
* This work contains confidential and proprietary information of
* BES. which is protected by copyright, trade secret,
* trademark and other intellectual property rights.
*
****************************************************************************/
#include "cmsis_os.h"
#include "list.h"
#include "hal_trace.h"
#include "hal_bootmode.h"
#include "hal_cmu.h"
#include "hal_sleep.h"
#include "app_key.h"
#include "app_factory.h"
#include "bt_drv_interface.h"
#include "bt_drv_reg_op.h"
#include "bluetooth.h"
#include "nvrecord.h"
#include "nvrecord_dev.h"
#include "nvrecord_env.h"
#include "resources.h"
#include "app_bt_stream.h"
#include "app_media_player.h"
#include "pmu.h"
// for init
#include "apps.h"
#include "app_status_ind.h"
#include "app_thread.h"
#include "app_key.h"
#include "app_pwl.h"
#include "app_overlay.h"
#include "app_battery.h"
#include "app_utils.h"
// for bt
#include "besbt.h"
#include "app_bt.h"
#include "app_factory_bt.h"
// for audio
#include "audioflinger.h"
#include "app_audio.h"
#include "app_utils.h"
// for progress
#include "hal_uart.h"
#include "tool_msg.h"
#include "factory_section.h"
#ifdef __FACTORY_MODE_SUPPORT__
#define APP_FACTORYMODE_RETRY_LIMITED (2)
typedef enum APP_FACTORYMODE_STATUS_INDICATION_T {
APP_FACTORYMODE_STATUS_INDICATION_RUNNING = 0,
APP_FACTORYMODE_STATUS_INDICATION_PASS,
APP_FACTORYMODE_STATUS_INDICATION_FAILED,
APP_FACTORYMODE_STATUS_INDICATION_INVALID,
APP_FACTORYMODE_STATUS_INDICATION_NUM
}APP_FACTORYMODE_STATUS_INDICATION_T;
static void app_factorymode_timehandler(void const *param);
void app_bt_key_shutdown(APP_KEY_STATUS *status, void *param);
void app_factorymode_result_set(bool result);
static osThreadId app_factorymode_tid= NULL;
static struct message_t send_msg = { { PREFIX_CHAR, }, };
static unsigned char send_seq = 0;
osTimerId app_factory_timer = NULL;
osTimerDef (APP_FACTORY_TIMER, app_factorymode_timehandler);
int app_factorymode_languageswitch_proc(void)
{
#ifdef MEDIA_PLAYER_SUPPORT
int lan;
int new_lan;
struct nvrecord_env_t *nvrecord_env;
APP_FACTORY_TRACE(1,"%s",__func__);
lan = app_play_audio_get_lang();
new_lan = lan;
app_play_audio_set_lang(new_lan);
nv_record_env_get(&nvrecord_env);
nvrecord_env->media_language.language = new_lan;
nv_record_env_set(nvrecord_env);
APP_FACTORY_TRACE(2,"languages old:%d new:%d",lan ,new_lan);
media_PlayAudio(AUD_ID_LANGUAGE_SWITCH, 0);
#endif
return 0;
}
void app_factorymode_languageswitch(APP_KEY_STATUS *status, void *param)
{
app_factorymode_languageswitch_proc();
}
void app_factorymode_enter(void)
{
APP_FACTORY_TRACE(1,"%s",__func__);
hal_sw_bootmode_set(HAL_SW_BOOTMODE_TEST_MODE|HAL_SW_BOOTMODE_TEST_SIGNALINGMODE);
hal_cmu_sys_reboot();
}
extern "C" {
static bool isInFactoryMode = false;
bool app_factorymode_get(void)
{
return isInFactoryMode;
}
void app_factorymode_set(bool set)
{
isInFactoryMode = set;
}
}
#ifdef POWERKEY_I2C_SWITCH
void app_factorymode_i2c_switch(APP_KEY_STATUS *status, void *param)
{
static int i = 0;
i++;
if (i & 1) {
TRACE(0,"set analog i2c mode !!!");
osDelay(100);
hal_iomux_set_analog_i2c();
} else {
hal_iomux_set_uart0();
osDelay(100);
TRACE(0,"hal_iomux_set_uart0 !!!");
}
}
#endif
#ifdef __IBRT_IBRT_TESTMODE__
void bt_drv_ibrt_test_key_click(APP_KEY_STATUS *status, void *param);
void bt_drv_ibrt_test_key_click(APP_KEY_STATUS *status, void *param)
{
btdrv_connect_ibrt_device(bt_addr);
}
#endif
void app_factorymode_key_init(void)
{
const APP_KEY_HANDLE app_factorymode_handle_cfg[] = {
#ifdef POWERKEY_I2C_SWITCH
{{APP_KEY_CODE_PWR,APP_KEY_EVENT_RAMPAGECLICK},"bt i2c key",app_factorymode_i2c_switch, NULL},
#endif
#ifdef __POWERKEY_CTRL_ONOFF_ONLY__
{{APP_KEY_CODE_PWR,APP_KEY_EVENT_UP},"bt function key",app_bt_key_shutdown, NULL},
#else
{{APP_KEY_CODE_PWR,APP_KEY_EVENT_LONGLONGPRESS},"bt function key",app_bt_key_shutdown, NULL},
#endif
#ifdef __IBRT_IBRT_TESTMODE__
{{APP_KEY_CODE_PWR,APP_KEY_EVENT_CLICK},"bt function key",bt_drv_ibrt_test_key_click, NULL},
#else
{{APP_KEY_CODE_PWR,APP_KEY_EVENT_CLICK},"bt function key",app_factorymode_languageswitch, NULL},
#endif
{{APP_KEY_CODE_PWR,APP_KEY_EVENT_DOUBLECLICK},"bt function key",app_factorymode_bt_xtalcalib, NULL},
{{APP_KEY_CODE_PWR,APP_KEY_EVENT_LONGPRESS},"bt function key",app_factorymode_bt_signalingtest, NULL},
};
uint8_t i = 0;
APP_FACTORY_TRACE(1,"%s",__func__);
app_key_handle_clear();
for (i=0; i<(sizeof(app_factorymode_handle_cfg)/sizeof(APP_KEY_HANDLE)); i++){
app_key_handle_registration(&app_factorymode_handle_cfg[i]);
}
}
static void app_factorymode_audioloopswitch(APP_KEY_STATUS *status, void *param)
{
static bool onaudioloop = false;
onaudioloop = onaudioloop?false:true;
if (onaudioloop)
app_audio_sendrequest(APP_FACTORYMODE_AUDIO_LOOP, (uint8_t)APP_BT_SETTING_OPEN, 0);
else
app_audio_sendrequest(APP_FACTORYMODE_AUDIO_LOOP, (uint8_t)APP_BT_SETTING_CLOSE, 0);
}
void app_factorymode_test_key_init(void)
{
const APP_KEY_HANDLE app_factorymode_handle_cfg[] = {
{{APP_KEY_CODE_PWR,APP_KEY_EVENT_CLICK},"bt function key",app_factorymode_audioloopswitch, NULL},
};
uint8_t i = 0;
APP_FACTORY_TRACE(1,"%s",__func__);
for (i=0; i<(sizeof(app_factorymode_handle_cfg)/sizeof(APP_KEY_HANDLE)); i++){
app_key_handle_registration(&app_factorymode_handle_cfg[i]);
}
}
void app_factorymode_result_clean(void)
{
osSignalClear(app_factorymode_tid, 0x01);
osSignalClear(app_factorymode_tid, 0x02);
}
void app_factorymode_result_set(bool result)
{
if (result)
osSignalSet(app_factorymode_tid ,0x01);
else
osSignalSet(app_factorymode_tid ,0x02);
}
bool app_factorymode_result_wait(void)
{
bool nRet;
osEvent evt;
while(1)
{
//wait any signal
evt = osSignalWait(0x0, osWaitForever);
//get role from signal value
if(evt.status == osEventSignal)
{
if(evt.value.signals & 0x01)
{
nRet = true;
break;
}
else if(evt.value.signals & 0x02)
{
nRet = false;
break;
}
}
}
return nRet;
}
static int app_factorymode_send_progress (uint8_t progress)
{
APP_MESSAGE_BLOCK msg;
msg.mod_id = APP_MODUAL_OHTER;
msg.msg_body.message_id = 2;
msg.msg_body.message_Param0 = progress;
app_mailbox_put(&msg);
return 0;
}
static int app_factorymode_send_code (uint32_t progress)
{
APP_MESSAGE_BLOCK msg;
msg.mod_id = APP_MODUAL_OHTER;
msg.msg_body.message_id = 3;
msg.msg_body.message_Param0 = progress;
app_mailbox_put(&msg);
return 0;
}
int app_factorymode_proc(void)
{
uint8_t cnt = 0;
bool nRet;
app_factorymode_tid = osThreadGetId();
app_factorymode_send_progress(60);
app_factorymode_bt_init_connect();
do{
app_factorymode_result_clean();
app_factorymode_bt_create_connect();
nRet = app_factorymode_result_wait();
}while(!nRet && ++cnt < APP_FACTORYMODE_RETRY_LIMITED);
if (!nRet)
goto exit;
app_factorymode_send_progress(90);
app_factorymode_result_clean();
if (!nRet)
goto exit;
app_factorymode_send_progress(100);
osDelay(100);
exit:
app_factorymode_result_clean();
if (nRet){
return 0;
}else{
return -1;
}
}
static unsigned char app_factorymode_msg_check_sum(unsigned char *buf, unsigned char len)
{
int i;
unsigned char sum = 0;
for (i = 0; i < len; i++) {
sum += buf[i];
}
return sum;
}
static int app_factorymode_msg_uart_send(const unsigned char *buf, size_t len)
{
uint32_t sent = 0;
while (sent < len) {
hal_uart_blocked_putc(HAL_UART_ID_0, buf[sent++]);
}
if (sent != len) {
return 1;
}
return 0;
}
static int app_factorymode_msg_send_ping(void)
{
int ret;
send_msg.hdr.type = 0x88;
send_msg.hdr.seq = send_seq++;
send_msg.hdr.len = 2;
send_msg.data[0] = 0xaa;
send_msg.data[1] = 0x55;
send_msg.data[2] = ~app_factorymode_msg_check_sum((unsigned char *)&send_msg, MSG_TOTAL_LEN(&send_msg) - 1);
ret = app_factorymode_msg_uart_send((unsigned char *)&send_msg, MSG_TOTAL_LEN(&send_msg));
return ret;
}
static int app_factorymode_msg_send_progress (uint8_t progress)
{
int ret;
send_msg.hdr.type = 0x88;
send_msg.hdr.seq = send_seq++;
send_msg.hdr.len = 2;
send_msg.data[0] = progress;
send_msg.data[1] = 100;
send_msg.data[2] = ~app_factorymode_msg_check_sum((unsigned char *)&send_msg, MSG_TOTAL_LEN(&send_msg) - 1);
ret = app_factorymode_msg_uart_send((unsigned char *)&send_msg, MSG_TOTAL_LEN(&send_msg));
return ret;
}
static int app_factorymode_msg_send_32bitcode(uint32_t code)
{
int ret;
send_msg.hdr.type = 0x88;
send_msg.hdr.seq = send_seq++;
send_msg.hdr.len = 4;
send_msg.data[0] = 0xf2;
*(uint32_t *)&(send_msg.data[1]) = code;
send_msg.data[4] = ~app_factorymode_msg_check_sum((unsigned char *)&send_msg, MSG_TOTAL_LEN(&send_msg) - 1);
ret = app_factorymode_msg_uart_send((unsigned char *)&send_msg, MSG_TOTAL_LEN(&send_msg));
return ret;
}
static int app_factorymode_process(APP_MESSAGE_BODY *msg_body)
{
if (msg_body->message_id == 1){
app_factorymode_msg_send_ping();
}
if (msg_body->message_id == 2){
app_factorymode_msg_send_progress(msg_body->message_Param0);
}
if (msg_body->message_id == 3){
app_factorymode_msg_send_32bitcode(msg_body->message_Param0);
}
return 0;
}
static int app_factorymode_uart_init(void)
{
struct HAL_UART_CFG_T uart_cfg;
memset(&uart_cfg, 0, sizeof(struct HAL_UART_CFG_T));
uart_cfg.parity = HAL_UART_PARITY_NONE,
uart_cfg.stop = HAL_UART_STOP_BITS_1,
uart_cfg.data = HAL_UART_DATA_BITS_8,
uart_cfg.flow = HAL_UART_FLOW_CONTROL_NONE,//HAL_UART_FLOW_CONTROL_RTSCTS,
uart_cfg.tx_level = HAL_UART_FIFO_LEVEL_1_2,
uart_cfg.rx_level = HAL_UART_FIFO_LEVEL_1_4,
uart_cfg.baud = 921600,
uart_cfg.dma_rx = false,
uart_cfg.dma_tx = false,
uart_cfg.dma_rx_stop_on_err = false;
hal_uart_close(HAL_UART_ID_0);
hal_uart_open(HAL_UART_ID_0, &uart_cfg);
return 0;
}
static void app_factorymode_timehandler(void const *param)
{
APP_MESSAGE_BLOCK msg;
msg.mod_id = APP_MODUAL_OHTER;
msg.msg_body.message_id = 1;
app_mailbox_put(&msg);
}
static uint8_t app_factorymode_indication_init(void)
{
struct APP_PWL_CFG_T cfg;
memset(&cfg, 0, sizeof(struct APP_PWL_CFG_T));
app_pwl_open();
app_pwl_setup(APP_PWL_ID_0, &cfg);
app_pwl_setup(APP_PWL_ID_1, &cfg);
return 0;
}
static uint8_t app_factorymode_status_indication(APP_FACTORYMODE_STATUS_INDICATION_T status)
{
struct APP_PWL_CFG_T cfg0;
struct APP_PWL_CFG_T cfg1;
APP_FACTORY_TRACE(2,"%s %d",__func__, status);
memset(&cfg0, 0, sizeof(struct APP_PWL_CFG_T));
memset(&cfg1, 0, sizeof(struct APP_PWL_CFG_T));
app_pwl_stop(APP_PWL_ID_0);
app_pwl_stop(APP_PWL_ID_1);
switch (status) {
case APP_FACTORYMODE_STATUS_INDICATION_RUNNING:
cfg0.part[0].level = 0;
cfg0.part[0].time = (300);
cfg0.part[1].level = 1;
cfg0.part[1].time = (300);
cfg0.parttotal = 2;
cfg0.startlevel = 0;
cfg0.periodic = true;
cfg1.part[0].level = 1;
cfg1.part[0].time = (300);
cfg1.part[1].level = 0;
cfg1.part[1].time = (300);
cfg1.parttotal = 2;
cfg1.startlevel = 1;
cfg1.periodic = true;
app_pwl_setup(APP_PWL_ID_0, &cfg0);
app_pwl_start(APP_PWL_ID_0);
app_pwl_setup(APP_PWL_ID_1, &cfg1);
app_pwl_start(APP_PWL_ID_1);
break;
case APP_FACTORYMODE_STATUS_INDICATION_PASS:
cfg0.part[0].level = 1;
cfg0.part[0].time = (5000);
cfg0.parttotal = 1;
cfg0.startlevel = 1;
cfg0.periodic = false;
app_pwl_setup(APP_PWL_ID_0, &cfg0);
app_pwl_start(APP_PWL_ID_0);
break;
case APP_FACTORYMODE_STATUS_INDICATION_FAILED:
cfg1.part[0].level = 1;
cfg1.part[0].time = (5000);
cfg1.parttotal = 1;
cfg1.startlevel = 1;
cfg1.periodic = false;
app_pwl_setup(APP_PWL_ID_1, &cfg1);
app_pwl_start(APP_PWL_ID_1);
break;
default:
break;
}
return 0;
}
int app_factorymode_init(uint32_t factorymode)
{
uint8_t cnt = 0;
int nRet = 0;
uint32_t capval = 0x00;
struct nvrecord_env_t *nvrecord_env;
APP_FACTORY_TRACE(1,"app_factorymode_init mode:%x\n", factorymode);
osThreadSetPriority(osThreadGetId(), osPriorityRealtime);
app_factorymode_uart_init();
#ifdef __WATCHER_DOG_RESET__
app_wdt_open(60);
#endif
app_sysfreq_req(APP_SYSFREQ_USER_APP_0, APP_SYSFREQ_52M);
list_init();
app_os_init();
app_factorymode_indication_init();
app_battery_open();
if (app_key_open(false)){
nRet = -1;
goto exit;
}
app_set_threadhandle(APP_MODUAL_OHTER, app_factorymode_process);
app_factory_timer = osTimerCreate (osTimer(APP_FACTORY_TIMER), osTimerPeriodic, NULL);
osTimerStart(app_factory_timer, 300);
app_factorymode_send_progress(10);
app_bt_init();
af_open();
app_audio_open();
app_overlay_open();
nv_record_env_init();
nvrec_dev_data_open();
nv_record_env_get(&nvrecord_env);
#ifdef MEDIA_PLAYER_SUPPORT
app_play_audio_set_lang(nvrecord_env->media_language.language);
app_voice_report(APP_STATUS_INDICATION_POWERON, 0);
#endif
app_status_indication_set(APP_STATUS_INDICATION_POWERON);
app_factorymode_status_indication(APP_FACTORYMODE_STATUS_INDICATION_RUNNING);
if (factorymode&HAL_SW_BOOTMODE_CALIB){
btdrv_start_bt();
app_factorymode_send_progress(20);
do {
nRet = app_factorymode_bt_xtalcalib_proc();
}while(nRet && cnt++<APP_FACTORYMODE_RETRY_LIMITED);
if (nRet)
goto err;
osDelay(200);
app_factorymode_send_progress(30);
}
nvrec_dev_get_xtal_fcap((unsigned int*)&capval);
app_factorymode_send_code(capval);
btdrv_start_bt();
bt_drv_reg_op_key_gen_after_reset(false);
app_factorymode_send_progress(40);
BesbtInit();
osDelay(600);
nRet = app_factorymode_proc();
if (nRet)
goto err;
app_factorymode_test_key_init();
//osTimerStop(app_factory_timer);
app_factorymode_status_indication(APP_FACTORYMODE_STATUS_INDICATION_PASS);
//wait forever
osSignalWait(0x01, osWaitForever);
goto exit;
err:
osTimerStop(app_factory_timer);
app_factorymode_status_indication(APP_FACTORYMODE_STATUS_INDICATION_FAILED);
app_factorymode_send_code(0xff);
osSignalWait(0x01, osWaitForever);
exit:
app_sysfreq_req(APP_SYSFREQ_USER_APP_0, APP_SYSFREQ_32K);
pmu_shutdown();
return nRet;
}
int app_factorymode_calib_only(void)
{
uint8_t cnt = 0;
int nRet = 0;
uint32_t capval = 0x00;
app_factorymode_uart_init();
#ifdef __WATCHER_DOG_RESET__
app_wdt_reopen(60);
#endif
app_sysfreq_req(APP_SYSFREQ_USER_APP_0, APP_SYSFREQ_52M);
list_init();
app_os_init();
nv_record_env_init();
nvrec_dev_data_open();
factory_section_open();
app_factorymode_indication_init();
app_set_threadhandle(APP_MODUAL_OHTER, app_factorymode_process);
app_factory_timer = osTimerCreate(osTimer(APP_FACTORY_TIMER),osTimerPeriodic,NULL);
osTimerStart(app_factory_timer,300);
app_factorymode_status_indication(APP_FACTORYMODE_STATUS_INDICATION_RUNNING);
app_factorymode_send_progress(10);
btdrv_start_bt();
osDelay(20);
app_factorymode_send_progress(20);
do {
nRet = app_factorymode_bt_xtalcalib_proc();
}while(nRet && ++cnt < APP_FACTORYMODE_RETRY_LIMITED);
if(nRet)
goto err;
nvrec_dev_get_xtal_fcap((unsigned int*)&capval);
app_factorymode_send_code(capval);
app_factorymode_send_progress(50);
osDelay(200);
app_factorymode_send_progress(80);
osDelay(100);
app_factorymode_send_progress(100);
app_factorymode_status_indication(APP_FACTORYMODE_STATUS_INDICATION_PASS);
osSignalWait(0x01, osWaitForever);
goto exit;
err:
osTimerStop(app_factory_timer);
app_factorymode_status_indication(APP_FACTORYMODE_STATUS_INDICATION_FAILED);
app_factorymode_send_code(0xff);
osSignalWait(0x01, osWaitForever);
exit:
app_sysfreq_req(APP_SYSFREQ_USER_APP_0, APP_SYSFREQ_32K);
pmu_shutdown();
return nRet;
}
#ifdef __USB_COMM__
// for usb
#include "usb_cdc.h"
#include "hal_timer.h"
#include "hwtimer_list.h"
#include "hal_usb.h"
#include "app_factory_cdc_comm.h"
#include "sys_api_cdc_comm.h"
static const struct USB_SERIAL_CFG_T cdc_cfg = {
.mode = USB_SERIAL_API_NONBLOCKING,
};
static void usb_serial_recv_timeout(void *param)
{
usb_serial_cancel_recv();
}
int app_factorymode_cdc_comm(void)
{
HWTIMER_ID timer;
pmu_usb_config(PMU_USB_CONFIG_TYPE_DEVICE);
usb_serial_open(&cdc_cfg);
osDelay(500);
hwtimer_init();
timer = hwtimer_alloc(usb_serial_recv_timeout, NULL);
ASSERT(timer, "Failed to alloc usb serial recv timer");
usb_serial_flush_recv_buffer();
usb_serial_init_xfer();
af_open();
comm_loop();
return 1;
}
#endif
#endif