[update] add callback for single gpio, add cdc_msc, i2s_es8311 adc onechan, mjpeg with crop demo

This commit is contained in:
jzlv 2023-11-09 15:19:03 +08:00
parent 4c12ce5324
commit 358a4176b3
51 changed files with 43021 additions and 13 deletions

View File

@ -373,6 +373,10 @@ void bflb_gpio_uart_init(struct bflb_device_s *dev, uint8_t pin, uint8_t uart_fu
int bflb_gpio_feature_control(struct bflb_device_s *dev, int cmd, size_t arg);
void bflb_gpio_irq_attach(uint8_t pin, void (*callback)(uint8_t pin));
void bflb_gpio_irq_detach(uint8_t pin);
#ifdef __cplusplus
}
#endif

View File

@ -1,6 +1,20 @@
#include "bflb_gpio.h"
#include "hardware/gpio_reg.h"
struct bflb_gpio_irq_callback {
void (*handler)(uint8_t pin);
};
#if defined(BL702) || defined(BL602) || defined(BL702L)
struct bflb_gpio_irq_callback g_gpio_irq_callback[32] = { 0 };
#elif defined(BL616)
struct bflb_gpio_irq_callback g_gpio_irq_callback[35] = { 0 };
#elif defined(BL606P) || defined(BL808)
struct bflb_gpio_irq_callback g_gpio_irq_callback[46] = { 0 };
#elif defined(BL628)
struct bflb_gpio_irq_callback g_gpio_irq_callback[35] = { 0 };
#endif
void bflb_gpio_init(struct bflb_device_s *dev, uint8_t pin, uint32_t cfgset)
{
uint32_t cfg = 0;
@ -496,3 +510,31 @@ int bflb_gpio_feature_control(struct bflb_device_s *dev, int cmd, size_t arg)
}
return ret;
}
struct bflb_device_s *g_gpio_int = NULL;
void gpio_all_isr(int irq, void *arg)
{
for (uint8_t i = 0; i < sizeof(g_gpio_irq_callback) / sizeof(struct bflb_gpio_irq_callback); i++) {
if (g_gpio_irq_callback[i].handler && bflb_gpio_get_intstatus(g_gpio_int, i)) {
bflb_gpio_int_clear(g_gpio_int, i);
g_gpio_irq_callback[i].handler(i);
}
}
}
void bflb_gpio_irq_attach(uint8_t pin, void (*callback)(uint8_t pin))
{
g_gpio_int = bflb_device_get_by_name("gpio");
bflb_gpio_int_mask(g_gpio_int, pin, true);
g_gpio_irq_callback[pin].handler = callback;
bflb_gpio_int_mask(g_gpio_int, pin, false);
bflb_irq_attach(g_gpio_int->irq_num, gpio_all_isr, NULL);
}
void bflb_gpio_irq_detach(uint8_t pin)
{
g_gpio_int = bflb_device_get_by_name("gpio");
bflb_gpio_int_mask(g_gpio_int, pin, true);
g_gpio_irq_callback[pin].handler = NULL;
}

View File

@ -6,15 +6,17 @@
#include <csi_core.h>
#endif
#ifndef BL_IOT_SDK
extern struct bflb_irq_info_s g_irqvector[];
static void irq_unexpected_isr(int irq, void *arg)
{
printf("irq :%d unregistered\r\n", irq);
}
#endif
void bflb_irq_initialize(void)
{
#ifndef BL_IOT_SDK
int i;
/* Point all interrupt vectors to the unexpected interrupt */
@ -22,6 +24,7 @@ void bflb_irq_initialize(void)
g_irqvector[i].handler = irq_unexpected_isr;
g_irqvector[i].arg = NULL;
}
#endif
}
ATTR_TCM_SECTION uintptr_t bflb_irq_save(void)
@ -50,8 +53,13 @@ int bflb_irq_attach(int irq, irq_callback isr, void *arg)
if (irq > CONFIG_IRQ_NUM) {
return -EINVAL;
}
#ifndef BL_IOT_SDK
g_irqvector[irq].handler = isr;
g_irqvector[irq].arg = arg;
#else
extern void bl_irq_register_with_ctx(int irqnum, void *handler, void *ctx);
bl_irq_register_with_ctx(irq, (void *)isr, arg);
#endif
return 0;
}
@ -60,8 +68,10 @@ int bflb_irq_detach(int irq)
if (irq > CONFIG_IRQ_NUM) {
return -EINVAL;
}
#ifndef BL_IOT_SDK
g_irqvector[irq].handler = irq_unexpected_isr;
g_irqvector[irq].arg = NULL;
#endif
return 0;
}

View File

@ -66,6 +66,69 @@ static const bflb_ef_ctrl_com_trim_cfg_t trim_list[] = {
.parity_addr = 0x7C * 8 + 12,
.value_addr = 0x7C * 8 + 0,
.value_len = 12,
},
{
.name = "xtal0",
.en_addr = 0x0C * 8 + 9,
.parity_addr = 0x0C * 8 + 8,
.value_addr = 0x0C * 8 + 2,
.value_len = 6,
},
{
.name = "xtal1",
.en_addr = 0x70 * 8 + 29,
.parity_addr = 0x70 * 8 + 28,
.value_addr = 0x70 * 8 + 22,
.value_len = 6,
},
{
.name = "xtal2",
.en_addr = 0x08 * 8 + 29,
.parity_addr = 0x08 * 8 + 28,
.value_addr = 0x08 * 8 + 22,
.value_len = 6,
},
{
.name = "key_enable_dac_dvdd",
.en_addr = 0x58 * 8 + 16,
.parity_addr = 0x58 * 8 + 15,
.value_addr = 0x58 * 8 + 13,
.value_len = 2,
},
{
.name = "key_enable_ldo11",
.en_addr = 0x58 * 8 + 12,
.parity_addr = 0x58 * 8 + 11,
.value_addr = 0x58 * 8 + 7,
.value_len = 4,
},
{
.name = "key_enable_tx_power_res",
.en_addr = 0x58 * 8 + 6,
.parity_addr = 0x58 * 8 + 5,
.value_addr = 0x58 * 8 + 0,
.value_len = 5,
},
{
.name = "key_disable_dac_dvdd",
.en_addr = 0x68 * 8 + 16,
.parity_addr = 0x68 * 8 + 15,
.value_addr = 0x68 * 8 + 13,
.value_len = 2,
},
{
.name = "key_disable_ldo11",
.en_addr = 0x68 * 8 + 12,
.parity_addr = 0x68 * 8 + 11,
.value_addr = 0x68 * 8 + 7,
.value_len = 4,
},
{
.name = "key_disable_tx_power_res",
.en_addr = 0x68 * 8 + 6,
.parity_addr = 0x68 * 8 + 5,
.value_addr = 0x68 * 8 + 0,
.value_len = 5,
}
};
@ -413,4 +476,4 @@ void bflb_efuse_read_sw_usage(uint32_t index, uint32_t *usage)
return;
}
bflb_ef_ctrl_read_direct(NULL, EF_DATA_EF_SW_USAGE_0_OFFSET + index * 4, (uint32_t *)usage, 1, 1);
}
}

View File

@ -77,4 +77,4 @@ buildall:
cleanall:
@for n in $(build_dirs); do make -C $$n clean; done
.PHONY: buildall cleanall
.PHONY: buildall cleanall

View File

@ -405,7 +405,7 @@ int main(void)
{
board_init();
mbedtls_aes_self_test(1);
// mbedtls_aes_self_test(1); /* mbedtls aes test uses dynamic iv(modifies last iv) but hardware does not support */
mbedtls_sha1_self_test(1);
mbedtls_sha256_self_test(1);
mbedtls_sha512_self_test(1);

View File

@ -0,0 +1,9 @@
cmake_minimum_required(VERSION 3.15)
include(proj.conf)
find_package(bouffalo_sdk REQUIRED HINTS $ENV{BL_SDK_BASE})
sdk_set_main_file(main.c)
project(adc_poll_onechan)

View File

@ -0,0 +1,13 @@
SDK_DEMO_PATH ?= .
BL_SDK_BASE ?= $(SDK_DEMO_PATH)/../../../..
export BL_SDK_BASE
CHIP ?= bl616
BOARD ?= bl616dk
CROSS_COMPILE ?= riscv64-unknown-elf-
# add custom cmake definition
#cmake_definition+=-Dxxx=sss
include $(BL_SDK_BASE)/project.build

View File

@ -0,0 +1,51 @@
# adc_poll_onechan
## Support CHIP
| CHIP | Remark |
|:----------------:|:------:|
|BL602/BL604 | |
|BL702/BL704/BL706 | |
|BL702L/BL704L | |
|BL616/BL618 | |
|BL808 | |
## Compile
- BL602/BL604
```
make CHIP=bl602 BOARD=bl602dk
```
- BL702/BL704/BL706
```
make CHIP=bl702 BOARD=bl702dk
```
- BL702L/BL704L
```
make CHIP=bl702l BOARD=bl702ldk
```
- BL616/BL618
```
make CHIP=bl616 BOARD=bl616dk
```
- BL808
```
make CHIP=bl808 BOARD=bl808dk CPU_ID=m0
make CHIP=bl808 BOARD=bl808dk CPU_ID=d0
```
## Flash
```
make flash CHIP=chip_name COMX=xxx # xxx is your com name
```

View File

@ -0,0 +1,11 @@
[cfg]
# 0: no erase, 1:programmed section erase, 2: chip erase
erase = 1
# skip mode set first para is skip addr, second para is skip len, multi-segment region with ; separated
skip_mode = 0x0, 0x0
# 0: not use isp mode, #1: isp mode
boot2_isp_mode = 0
[FW]
filedir = ./build/build_out/adc*_$(CHIPNAME).bin
address = 0x000000

View File

@ -0,0 +1,71 @@
#include "bflb_adc.h"
#include "bflb_mtimer.h"
#include "board.h"
#define TEST_ADC_CHANNEL_x ADC_CHANNEL_8
static struct bflb_adc_channel_s chan[1] = {
{ .pos_chan = TEST_ADC_CHANNEL_x,
.neg_chan = ADC_CHANNEL_GND }
};
#define TEST_COUNT 10
static struct bflb_device_s *adc;
static uint32_t raw_data;
void test_adc_poll(void)
{
struct bflb_adc_result_s result;
board_adc_gpio_init();
adc = bflb_device_get_by_name("adc");
/* adc clock = XCLK / 2 / 32 */
struct bflb_adc_config_s cfg;
cfg.clk_div = ADC_CLK_DIV_32;
cfg.scan_conv_mode = false;
cfg.continuous_conv_mode = true; /* do not support single mode */
cfg.differential_mode = false;
cfg.resolution = ADC_RESOLUTION_16B;
cfg.vref = ADC_VREF_3P2V;
bflb_adc_init(adc, &cfg);
bflb_adc_channel_config(adc, chan, 1);
bflb_adc_start_conversion(adc);
raw_data = 0;
for (uint16_t i = 0; i < TEST_COUNT; i++) {
while (bflb_adc_get_count(adc) == 0) {
bflb_mtimer_delay_ms(1);
}
if (i > 4) {
raw_data += bflb_adc_read_raw(adc);
}
}
raw_data = raw_data / 5;
bflb_adc_stop_conversion(adc);
bflb_adc_parse_result(adc, &raw_data, &result, 1);
printf("raw data:%08x\r\n", raw_data);
printf("pos chan %d,%d mv \r\n", result.pos_chan, result.millivolt);
bflb_adc_deinit(adc);
}
int main(void)
{
board_init();
while (1) {
test_adc_poll();
bflb_mtimer_delay_ms(1000);
}
}

View File

@ -0,0 +1 @@
set(CONFIG_COMPONENT1 1)

View File

@ -0,0 +1,9 @@
cmake_minimum_required(VERSION 3.15)
include(proj.conf)
find_package(bouffalo_sdk REQUIRED HINTS $ENV{BL_SDK_BASE})
sdk_set_main_file(main.c)
project(auadc_audac_loopback)

View File

@ -0,0 +1,13 @@
SDK_DEMO_PATH ?= .
BL_SDK_BASE ?= $(SDK_DEMO_PATH)/../../../..
export BL_SDK_BASE
CHIP ?= bl616
BOARD ?= bl616dk
CROSS_COMPILE ?= riscv64-unknown-elf-
# add custom cmake definition
#cmake_definition+=-Dxxx=sss
include $(BL_SDK_BASE)/project.build

View File

@ -0,0 +1,22 @@
# audac_play_from_mem
## Support CHIP
| CHIP | Remark |
|:----------------:|:------:|
|BL616/BL618 | |
## Compile
- BL616/BL618
```
make CHIP=bl616 BOARD=bl616dk
```
## Flash
```
make flash CHIP=chip_name COMX=xxx # xxx is your com name
```

View File

@ -0,0 +1,12 @@
[cfg]
# 0: no erase, 1:programmed section erase, 2: chip erase
erase = 1
# skip mode set first para is skip addr, second para is skip len, multi-segment region with ; separated
skip_mode = 0x0, 0x0
# 0: not use isp mode, #1: isp mode
boot2_isp_mode = 0
[FW]
filedir = ./build/build_out/auadc*_$(CHIPNAME).bin
address = 0x000000

View File

@ -0,0 +1,208 @@
#include "bflb_auadc.h"
#include "bflb_audac.h"
#include "bflb_gpio.h"
#include "bflb_dma.h"
#include "bl616_glb.h"
#include "board.h"
struct bflb_device_s *auadc_dma_hd;
struct bflb_device_s *audac_dma_hd;
struct bflb_device_s *auadc_hd;
struct bflb_device_s *audac_hd;
struct bflb_dma_channel_lli_pool_s auadc_dma_lli_pool[10];
struct bflb_dma_channel_lli_pool_s audac_dma_lli_pool[10];
uint16_t audio_loopback_buff[8 * 1000];
void auadc_dma_callback(void *arg)
{
static uint16_t num = 0;
num++;
printf("scyle_n:%d\r\n", num);
}
/* audio gpio init*/
void audio_gpio_init(void)
{
struct bflb_device_s *gpio;
gpio = bflb_device_get_by_name("gpio");
/* auadc input */
bflb_gpio_init(gpio, GPIO_PIN_27, GPIO_ANALOG | GPIO_SMT_EN | GPIO_DRV_0); /* ain_ch4 */
bflb_gpio_init(gpio, GPIO_PIN_28, GPIO_ANALOG | GPIO_SMT_EN | GPIO_DRV_0); /* ain_ch5 */
/* audac pwm output mode */
// bflb_gpio_init(gpio, GPIO_PIN_14, GPIO_FUNC_AUDAC_PWM | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2);
// bflb_gpio_init(gpio, GPIO_PIN_15, GPIO_FUNC_AUDAC_PWM | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2);
// bflb_gpio_init(gpio, GPIO_PIN_22, GPIO_FUNC_AUDAC_PWM | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2);
// bflb_gpio_init(gpio, GPIO_PIN_23, GPIO_FUNC_AUDAC_PWM | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2);
// bflb_gpio_init(gpio, GPIO_PIN_27, GPIO_FUNC_AUDAC_PWM | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2);
// bflb_gpio_init(gpio, GPIO_PIN_28, GPIO_FUNC_AUDAC_PWM | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2);
/* audac gpdac output mode */
bflb_gpio_init(gpio, GPIO_PIN_2, GPIO_ANALOG | GPIO_SMT_EN | GPIO_DRV_0);
bflb_gpio_init(gpio, GPIO_PIN_3, GPIO_ANALOG | GPIO_SMT_EN | GPIO_DRV_0);
}
/* audio adc init */
static void auadc_init(void)
{
/* audio adc config */
struct bflb_auadc_init_config_s auadc_init_cfg = {
.sampling_rate = AUADC_SAMPLING_RATE_32K,
.input_mode = AUADC_INPUT_MODE_ADC,
.data_format = AUADC_DATA_FORMAT_16BIT,
.fifo_threshold = 3,
};
/* audio adc analog config */
struct bflb_auadc_adc_init_config_s auadc_analog_init_cfg = {
.auadc_analog_en = true,
.adc_mode = AUADC_ADC_MODE_AUDIO,
.adc_pga_mode = AUADC_ADC_PGA_MODE_AC_DIFFER,
.adc_pga_posi_ch = AUADC_ADC_ANALOG_CH_4,
.adc_pga_nega_ch = AUADC_ADC_ANALOG_CH_5,
.adc_pga_gain = 21,
};
/* clock cfg */
GLB_Config_AUDIO_PLL_To_491P52M();
GLB_PER_Clock_UnGate(GLB_AHB_CLOCK_AUDIO);
/* auadc init */
auadc_hd = bflb_device_get_by_name("auadc");
bflb_auadc_init(auadc_hd, &auadc_init_cfg);
bflb_auadc_adc_init(auadc_hd, &auadc_analog_init_cfg);
/* auadc enable dma */
bflb_auadc_link_rxdma(auadc_hd, true);
}
/* audio adc dma init */
void auadc_dma_init(void)
{
uint32_t dma_lli_cnt;
struct bflb_dma_channel_lli_transfer_s transfers[1];
struct bflb_dma_channel_config_s auadc_dma_cfg;
auadc_dma_cfg.direction = DMA_PERIPH_TO_MEMORY;
auadc_dma_cfg.src_req = DMA_REQUEST_AUADC_RX;
auadc_dma_cfg.dst_req = DMA_REQUEST_NONE;
auadc_dma_cfg.src_addr_inc = DMA_ADDR_INCREMENT_DISABLE;
auadc_dma_cfg.dst_addr_inc = DMA_ADDR_INCREMENT_ENABLE;
auadc_dma_cfg.src_burst_count = DMA_BURST_INCR4;
auadc_dma_cfg.dst_burst_count = DMA_BURST_INCR4;
auadc_dma_cfg.src_width = DMA_DATA_WIDTH_16BIT;
auadc_dma_cfg.dst_width = DMA_DATA_WIDTH_16BIT;
auadc_dma_hd = bflb_device_get_by_name("dma0_ch0");
bflb_dma_channel_init(auadc_dma_hd, &auadc_dma_cfg);
bflb_dma_channel_irq_attach(auadc_dma_hd, auadc_dma_callback, NULL);
transfers[0].src_addr = (uint32_t)DMA_ADDR_AUADC_RDR;
transfers[0].dst_addr = (uint32_t)audio_loopback_buff;
transfers[0].nbytes = sizeof(audio_loopback_buff);
dma_lli_cnt = bflb_dma_channel_lli_reload(auadc_dma_hd, auadc_dma_lli_pool, 10, transfers, 1);
bflb_dma_channel_lli_link_head(auadc_dma_hd, auadc_dma_lli_pool, dma_lli_cnt);
}
/* audio dac init */
static void audac_init(void)
{
/* audio dac config */
struct bflb_audac_init_config_s audac_init_cfg = {
.sampling_rate = AUDAC_SAMPLING_RATE_32K,
.output_mode = AUDAC_OUTPUT_MODE_GPDAC_CH_A_B, /* gpdac output */
.source_channels_num = AUDAC_SOURCE_CHANNEL_SINGLE,
.mixer_mode = AUDAC_MIXER_MODE_ONLY_L,
.data_format = AUDAC_DATA_FORMAT_16BIT,
.fifo_threshold = 3,
};
/* audio dac volume config */
struct bflb_audac_volume_config_s audac_volume_cfg = {
.mute_ramp_en = true,
.mute_up_ramp_rate = AUDAC_RAMP_RATE_FS_32,
.mute_down_ramp_rate = AUDAC_RAMP_RATE_FS_8,
.volume_update_mode = AUDAC_VOLUME_UPDATE_MODE_RAMP,
.volume_ramp_rate = AUDAC_RAMP_RATE_FS_128,
.volume_zero_cross_timeout = AUDAC_RAMP_RATE_FS_128,
};
/* clock cfg */
GLB_Config_AUDIO_PLL_To_491P52M();
GLB_PER_Clock_UnGate(GLB_AHB_CLOCK_AUDIO);
/* audac init */
audac_hd = bflb_device_get_by_name("audac");
bflb_audac_init(audac_hd, &audac_init_cfg);
bflb_audac_feature_control(audac_hd, AUDAC_CMD_SET_VOLUME_VAL, (size_t)(-5 * 2));
bflb_audac_volume_init(audac_hd, &audac_volume_cfg);
/* audac enable dma */
bflb_audac_link_rxdma(audac_hd, true);
}
/* audio dac dma init */
void audac_dma_init(void)
{
uint32_t dma_lli_cnt;
struct bflb_dma_channel_lli_transfer_s transfers[1];
struct bflb_dma_channel_config_s audac_dma_cfg;
audac_dma_cfg.direction = DMA_MEMORY_TO_PERIPH;
audac_dma_cfg.src_req = DMA_REQUEST_NONE;
audac_dma_cfg.dst_req = DMA_REQUEST_AUDAC_TX;
audac_dma_cfg.src_addr_inc = DMA_ADDR_INCREMENT_ENABLE;
audac_dma_cfg.dst_addr_inc = DMA_ADDR_INCREMENT_DISABLE;
audac_dma_cfg.src_burst_count = DMA_BURST_INCR4;
audac_dma_cfg.dst_burst_count = DMA_BURST_INCR4;
audac_dma_cfg.src_width = DMA_DATA_WIDTH_16BIT;
audac_dma_cfg.dst_width = DMA_DATA_WIDTH_16BIT;
audac_dma_hd = bflb_device_get_by_name("dma0_ch1");
bflb_dma_channel_init(audac_dma_hd, &audac_dma_cfg);
transfers[0].src_addr = (uint32_t)audio_loopback_buff;
transfers[0].dst_addr = (uint32_t)DMA_ADDR_AUDAC_TDR;
transfers[0].nbytes = sizeof(audio_loopback_buff);
dma_lli_cnt = bflb_dma_channel_lli_reload(audac_dma_hd, audac_dma_lli_pool, 10, transfers, 1);
bflb_dma_channel_lli_link_head(audac_dma_hd, audac_dma_lli_pool, dma_lli_cnt);
}
int main(void)
{
/* board init */
board_init();
printf("audac case start \r\n");
/* gpio init */
audio_gpio_init();
/* auadc init */
auadc_init();
auadc_dma_init();
bflb_dma_channel_start(auadc_dma_hd);
bflb_auadc_feature_control(auadc_hd, AUADC_CMD_RECORD_START, 0);
/* delay 10ms */
bflb_mtimer_delay_ms(10);
/* audac init */
audac_init();
audac_dma_init();
bflb_dma_channel_start(audac_dma_hd);
bflb_audac_feature_control(audac_hd, AUDAC_CMD_PLAY_START, 0);
printf("audac case end \r\n");
while (1) {
bflb_mtimer_delay_ms(1);
}
}

View File

@ -0,0 +1,5 @@
set(CONFIG_BFLOG 0)
set(CONFIG_VSNPRINTF_FLOAT 1)
set(CONFIG_VSNPRINTF_FLOAT_EX 1)
set(CONFIG_VSNPRINTF_LONG_LONG 1)

View File

@ -0,0 +1,51 @@
# flash_get_image_hash
## Support CHIP
| CHIP | Remark |
|:----------------:|:------:|
|BL602/BL604 | |
|BL702/BL704/BL706 | |
|BL702L/BL704L | |
|BL616/BL618 | |
|BL808 | |
## Compile
- BL602/BL604
```
make CHIP=bl602 BOARD=bl602dk
```
- BL702/BL704/BL706
```
make CHIP=bl702 BOARD=bl702dk
```
- BL702L/BL704L
```
make CHIP=bl702l BOARD=bl702ldk
```
- BL616/BL618
```
make CHIP=bl616 BOARD=bl616dk
```
- BL808
```
make CHIP=bl808 BOARD=bl808dk CPU_ID=m0
make CHIP=bl808 BOARD=bl808dk CPU_ID=d0
```
## Flash
```
make flash CHIP=chip_name COMX=xxx # xxx is your com name
```

View File

@ -7,13 +7,11 @@
struct bflb_device_s *gpio;
struct bflb_device_s *uart0;
void gpio_isr(int irq, void *arg)
void gpio0_isr(uint8_t pin)
{
static int i = 0;
bool intstatus = bflb_gpio_get_intstatus(gpio, GPIO_PIN_0);
if (intstatus) {
bflb_gpio_int_clear(gpio, GPIO_PIN_0);
printf("%d\r\n", i++);
static uint32_t i = 0;
if (pin == GPIO_PIN_0) {
printf("i:%d\r\n", i++);
}
}
@ -33,10 +31,9 @@ int set_int_mode(int argc, char **argv)
}
bflb_irq_disable(gpio->irq_num);
bflb_gpio_init(gpio, GPIO_PIN_0, GPIO_INPUT | GPIO_FLOAT | GPIO_SMT_EN);
bflb_gpio_init(gpio, GPIO_PIN_0, GPIO_INPUT | GPIO_PULLUP | GPIO_SMT_EN);
bflb_gpio_int_init(gpio, GPIO_PIN_0, atoi(argv[1]));
bflb_gpio_int_mask(gpio, GPIO_PIN_0, false);
bflb_irq_attach(gpio->irq_num, gpio_isr, NULL);
bflb_gpio_irq_attach(GPIO_PIN_0, gpio0_isr);
bflb_irq_enable(gpio->irq_num);
return 0;

View File

@ -0,0 +1,9 @@
cmake_minimum_required(VERSION 3.15)
include(proj.conf)
find_package(bouffalo_sdk REQUIRED HINTS $ENV{BL_SDK_BASE})
sdk_set_main_file(main.c)
project(gpio_output_with_input)

View File

@ -0,0 +1,13 @@
SDK_DEMO_PATH ?= .
BL_SDK_BASE ?= $(SDK_DEMO_PATH)/../../../..
export BL_SDK_BASE
CHIP ?= bl616
BOARD ?= bl616dk
CROSS_COMPILE ?= riscv64-unknown-elf-
# add custom cmake definition
#cmake_definition+=-Dxxx=sss
include $(BL_SDK_BASE)/project.build

View File

@ -0,0 +1,51 @@
# gpio_output_with_input
## Support CHIP
| CHIP | Remark |
|:----------------:|:------:|
|BL602/BL604 | |
|BL702/BL704/BL706 | |
|BL702L/BL704L | |
|BL616/BL618 | |
|BL808 | |
## Compile
- BL602/BL604
```
make CHIP=bl602 BOARD=bl602dk
```
- BL702/BL704/BL706
```
make CHIP=bl702 BOARD=bl702dk
```
- BL702L/BL704L
```
make CHIP=bl702l BOARD=bl702ldk
```
- BL616/BL618
```
make CHIP=bl616 BOARD=bl616dk
```
- BL808
```
make CHIP=bl808 BOARD=bl808dk CPU_ID=m0
make CHIP=bl808 BOARD=bl808dk CPU_ID=d0
```
## Flash
```
make flash CHIP=chip_name COMX=xxx # xxx is your com name
```

View File

@ -0,0 +1,11 @@
[cfg]
# 0: no erase, 1:programmed section erase, 2: chip erase
erase = 1
# skip mode set first para is skip addr, second para is skip len, multi-segment region with ; separated
skip_mode = 0x0, 0x0
# 0: not use isp mode, #1: isp mode
boot2_isp_mode = 0
[FW]
filedir = ./build/build_out/gpio*_$(CHIPNAME).bin
address = 0x000000

View File

@ -0,0 +1,23 @@
#include "bflb_gpio.h"
#include "board.h"
struct bflb_device_s *gpio;
int main(void)
{
board_init();
gpio = bflb_device_get_by_name("gpio");
printf("gpio output\r\n");
bflb_gpio_init(gpio, GPIO_PIN_0, GPIO_OUTPUT | GPIO_INPUT | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_0);
while (1) {
bflb_gpio_set(gpio, GPIO_PIN_0);
printf("GPIO_PIN_0=%x\r\n", bflb_gpio_read(gpio, GPIO_PIN_0));
bflb_mtimer_delay_ms(2000);
bflb_gpio_reset(gpio, GPIO_PIN_0);
printf("GPIO_PIN_0=%x\r\n", bflb_gpio_read(gpio, GPIO_PIN_0));
bflb_mtimer_delay_ms(2000);
}
}

View File

@ -0,0 +1 @@
set(CONFIG_COMPONENT1 1)

View File

@ -0,0 +1,11 @@
cmake_minimum_required(VERSION 3.15)
include(proj.conf)
find_package(bouffalo_sdk REQUIRED HINTS $ENV{BL_SDK_BASE})
sdk_add_include_directories(.)
target_sources(app PRIVATE bsp_es8311.c)
sdk_set_main_file(main.c)
project(i2s_es8311)

View File

@ -0,0 +1,13 @@
SDK_DEMO_PATH ?= .
BL_SDK_BASE ?= $(SDK_DEMO_PATH)/../../../..
export BL_SDK_BASE
CHIP ?= bl616
BOARD ?= bl616dk
CROSS_COMPILE ?= riscv64-unknown-elf-
# add custom cmake definition
#cmake_definition+=-Dxxx=sss
include $(BL_SDK_BASE)/project.build

View File

@ -0,0 +1,22 @@
# i2s_es8311
## Support CHIP
| CHIP | Remark |
|:----------------:|:------:|
|BL616/BL618 | |
## Compile
- BL616/BL618
```
make CHIP=bl616 BOARD=bl616dk
```
## Flash
```
make flash CHIP=chip_name COMX=xxx # xxx is your com name
```

View File

@ -0,0 +1,751 @@
/**
* @file bsp_es8311.c
* @brief
*
* Copyright (c) 2023 Bouffalolab team
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
*/
#include "bflb_i2c.h"
#include "bsp_es8311.h"
// ES8311 I2C addr 0x18 0x19
#define ES8311_I2C_SLAVE_ADDR 0x18
/*
* to define the clock soure of MCLK
*/
#define FROM_MCLK_PIN (0)
#define FROM_SCLK_PIN (1)
/*
* to define whether to reverse the clock
*/
#define INVERT_MCLK 0 // do not invert
#define INVERT_SCLK 0
#define IS_DMIC 0 // Is it a digital microphone
#define MCLK_DIV_FRE 256
/*
* Clock coefficient structer
*/
struct _coeff_div {
uint32_t mclk; /* mclk frequency */
uint32_t rate; /* sample rate */
uint8_t pre_div; /* the pre divider with range from 1 to 8 */
uint8_t pre_multi; /* the pre multiplier with x1, x2, x4 and x8 selection */
uint8_t adc_div; /* adcclk divider */
uint8_t dac_div; /* dacclk divider */
uint8_t fs_mode; /* double speed or single speed, =0, ss, =1, ds */
uint8_t lrck_h; /* adclrck divider and daclrck divider */
uint8_t lrck_l;
uint8_t bclk_div; /* sclk divider */
uint8_t adc_osr; /* adc osr */
uint8_t dac_osr; /* dac osr */
};
/* codec hifi mclk clock divider coefficients */
static const struct _coeff_div coeff_div[] = {
//mclk rate pre_div mult adc_div dac_div fs_mode lrch lrcl bckdiv osr
/* 8k */
{12288000, 8000 , 0x06, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x20},
{18432000, 8000 , 0x03, 0x02, 0x03, 0x03, 0x00, 0x05, 0xff, 0x18, 0x10, 0x20},
{16384000, 8000 , 0x08, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x20},
{8192000 , 8000 , 0x04, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x20},
{6144000 , 8000 , 0x03, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x20},
{4096000 , 8000 , 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x20},
{3072000 , 8000 , 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x20},
{2048000 , 8000 , 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x20},
{1536000 , 8000 , 0x03, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x20},
{1024000 , 8000 , 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x20},
/* 11.025k */
{11289600, 11025, 0x04, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x20},
{5644800 , 11025, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x20},
{2822400 , 11025, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x20},
{1411200 , 11025, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x20},
/* 12k */
{12288000, 12000, 0x04, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x20},
{6144000 , 12000, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x20},
{3072000 , 12000, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x20},
{1536000 , 12000, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x20},
/* 16k */
{12288000, 16000, 0x03, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x20},
{18432000, 16000, 0x03, 0x02, 0x03, 0x03, 0x00, 0x02, 0xff, 0x0c, 0x10, 0x20},
{16384000, 16000, 0x04, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x20},
{8192000 , 16000, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x20},
{6144000 , 16000, 0x03, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x20},
{4096000 , 16000, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x20},
{3072000 , 16000, 0x03, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x20},
{2048000 , 16000, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x20},
{1536000 , 16000, 0x03, 0x08, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x20},
{1024000 , 16000, 0x01, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x20},
/* 22.05k */
{11289600, 22050, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{5644800 , 22050, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{2822400 , 22050, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{1411200 , 22050, 0x01, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
/* 24k */
{12288000, 24000, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{18432000, 24000, 0x03, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{6144000 , 24000, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{3072000 , 24000, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{1536000 , 24000, 0x01, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
/* 32k */
{12288000, 32000, 0x03, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{18432000, 32000, 0x03, 0x04, 0x03, 0x03, 0x00, 0x02, 0xff, 0x0c, 0x10, 0x10},
{16384000, 32000, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{8192000 , 32000, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{6144000 , 32000, 0x03, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{4096000 , 32000, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{3072000 , 32000, 0x03, 0x08, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{2048000 , 32000, 0x01, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{1536000 , 32000, 0x03, 0x08, 0x01, 0x01, 0x01, 0x00, 0x7f, 0x02, 0x10, 0x10},
{1024000 , 32000, 0x01, 0x08, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
/* 44.1k */
{11289600, 44100, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{5644800 , 44100, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{2822400 , 44100, 0x01, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{1411200 , 44100, 0x01, 0x08, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
/* 48k */
{12288000, 48000, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{18432000, 48000, 0x03, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{6144000 , 48000, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{3072000 , 48000, 0x01, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{1536000 , 48000, 0x01, 0x08, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
/* 64k */
{12288000, 64000, 0x03, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{18432000, 64000, 0x03, 0x04, 0x03, 0x03, 0x01, 0x01, 0x7f, 0x06, 0x10, 0x10},
{16384000, 64000, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{8192000 , 64000, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{6144000 , 64000, 0x01, 0x04, 0x03, 0x03, 0x01, 0x01, 0x7f, 0x06, 0x10, 0x10},
{4096000 , 64000, 0x01, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{3072000 , 64000, 0x01, 0x08, 0x03, 0x03, 0x01, 0x01, 0x7f, 0x06, 0x10, 0x10},
{2048000 , 64000, 0x01, 0x08, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{1536000 , 64000, 0x01, 0x08, 0x01, 0x01, 0x01, 0x00, 0xbf, 0x03, 0x18, 0x18},
{1024000 , 64000, 0x01, 0x08, 0x01, 0x01, 0x01, 0x00, 0x7f, 0x02, 0x10, 0x10},
/* 88.2k */
{11289600, 88200, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{5644800 , 88200, 0x01, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{2822400 , 88200, 0x01, 0x08, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{1411200 , 88200, 0x01, 0x08, 0x01, 0x01, 0x01, 0x00, 0x7f, 0x02, 0x10, 0x10},
/* 96k */
{12288000, 96000, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{18432000, 96000, 0x03, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{6144000 , 96000, 0x01, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{3072000 , 96000, 0x01, 0x08, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{1536000 , 96000, 0x01, 0x08, 0x01, 0x01, 0x01, 0x00, 0x7f, 0x02, 0x10, 0x10},
};
static int get_es8311_mclk_src(void)
{
return FROM_SCLK_PIN;
}
/*
* look for the coefficient in coeff_div[] table
*/
static int get_coeff(uint32_t mclk, uint32_t rate)
{
for (int i = 0; i < (sizeof(coeff_div) / sizeof(coeff_div[0])); i++) {
if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk)
return i;
}
return -1;
}
static struct bflb_device_s *i2c0;
static struct bflb_i2c_msg_s msgs[2];
int es8311_i2c_init(void)
{
i2c0 = bflb_device_get_by_name("i2c0");
if (i2c0 == NULL) {
return -1;
}
bflb_i2c_init(i2c0, 200000);
return 0;
}
int es8311_write_reg(uint8_t addr, uint8_t data)
{
msgs[0].addr = ES8311_I2C_SLAVE_ADDR;
msgs[0].flags = I2C_M_NOSTOP;
msgs[0].buffer = &addr;
msgs[0].length = 1;
msgs[1].flags = 0;
msgs[1].buffer = &data;
msgs[1].length = 1;
return bflb_i2c_transfer(i2c0, msgs, 2);
}
int es8311_read_reg(uint8_t addr, uint8_t *rdata)
{
msgs[0].addr = ES8311_I2C_SLAVE_ADDR;
msgs[0].flags = I2C_M_NOSTOP;
msgs[0].buffer = &addr;
msgs[0].length = 1;
msgs[1].flags = I2C_M_READ;
msgs[1].buffer = rdata;
msgs[1].length = 1;
return bflb_i2c_transfer(i2c0, msgs, 2);
}
/*
* set es8311 dac mute or not
* if mute = 0, dac un-mute
* if mute = 1, dac mute
*/
static void es8311_mute(int mute)
{
uint8_t regv;
printf("Enter into es8311_mute(), mute = %d\r\n", mute);
es8311_read_reg(ES8311_DAC_REG31, &regv);
regv &= 0x9f;
if (mute) {
es8311_write_reg(ES8311_SYSTEM_REG12, 0x02);
es8311_write_reg(ES8311_DAC_REG31, (regv | 0x60));
es8311_write_reg(ES8311_DAC_REG32, 0x00);
es8311_write_reg(ES8311_DAC_REG37, 0x08);
} else {
es8311_write_reg(ES8311_DAC_REG31, regv);
es8311_write_reg(ES8311_SYSTEM_REG12, 0x00);
}
}
/*
* set es8311 into suspend mode
*/
static void es8311_suspend(void)
{
printf("Enter into es8311_suspend()\r\n");
es8311_write_reg(ES8311_DAC_REG32, 0x00);
es8311_write_reg(ES8311_ADC_REG17, 0x00);
es8311_write_reg(ES8311_SYSTEM_REG0E, 0xFF);
es8311_write_reg(ES8311_SYSTEM_REG12, 0x02);
es8311_write_reg(ES8311_SYSTEM_REG14, 0x00);
es8311_write_reg(ES8311_SYSTEM_REG0D, 0xFA);
es8311_write_reg(ES8311_ADC_REG15, 0x00);
es8311_write_reg(ES8311_DAC_REG37, 0x08);
es8311_write_reg(ES8311_GP_REG45, 0x01);
}
void es8311_reg_dump(void)
{
int i;
uint8_t tmp;
// es8311_read_reg(ES8311_CHIP_ID1, &tmp);
// printf("Reg[%02d]=0x%02x \n", ES8311_CHIP_ID1, tmp);
for (i = 0; i < 0X45; i++) {
if (es8311_read_reg(i, &tmp) != 0) {
printf("iic read err\r\n");
}
printf("Reg[%02d]=0x%02x \r\n", i, tmp);
}
}
int es8311_config_fmt(i2s_es8311_format_t fmt)
{
int ret = 0;
uint8_t adc_iface = 0, dac_iface = 0;
ret |= es8311_read_reg(ES8311_SDPIN_REG09, &dac_iface);
ret |= es8311_read_reg(ES8311_SDPOUT_REG0A, &dac_iface);
switch (fmt) {
case ES8311_I2S_NORMAL:
printf("ES8311 in I2S Format\r\n");
dac_iface &= 0xFC;
adc_iface &= 0xFC;
break;
case ES8311_I2S_LEFT:
case ES8311_I2S_RIGHT:
printf("ES8311 in LJ Format\r\n");
adc_iface &= 0xFC;
dac_iface &= 0xFC;
adc_iface |= 0x01;
dac_iface |= 0x01;
break;
case ES8311_I2S_DSP:
printf("ES8311 in DSP-A Format\r\n");
adc_iface &= 0xDC;
dac_iface &= 0xDC;
adc_iface |= 0x03;
dac_iface |= 0x03;
break;
default:
dac_iface &= 0xFC;
adc_iface &= 0xFC;
break;
}
ret |= es8311_write_reg(ES8311_SDPIN_REG09, dac_iface);
ret |= es8311_write_reg(ES8311_SDPOUT_REG0A, adc_iface);
return ret;
}
int es8311_set_bits_per_sample(i2s_es8311_bits_t bits)
{
int ret = 0;
uint8_t adc_iface = 0, dac_iface = 0;
ret |= es8311_read_reg(ES8311_SDPIN_REG09, &dac_iface);
ret |= es8311_read_reg(ES8311_SDPOUT_REG0A, &dac_iface);
switch (bits) {
case ES8311_BIT_LENGTH_16BITS:
dac_iface |= 0x0c;
adc_iface |= 0x0c;
break;
case ES8311_BIT_LENGTH_24BITS:
break;
case ES8311_BIT_LENGTH_32BITS:
dac_iface |= 0x10;
adc_iface |= 0x10;
break;
default:
dac_iface |= 0x0c;
adc_iface |= 0x0c;
break;
}
ret |= es8311_write_reg(ES8311_SDPIN_REG09, dac_iface);
ret |= es8311_write_reg(ES8311_SDPOUT_REG0A, adc_iface);
return ret;
}
int es8311_init(i2s_es8311_t *i2s_cfg)
{
int ret = 0;
int coeff;
uint8_t read_data, datmp;
ret = es8311_i2c_init();
if (ret < 0) {
printf("es8311 i2c init failed!\r\n");
return ret;
}
ret |= es8311_read_reg(ES8311_CHIP_ID1, &read_data);
if (read_data != ES8311_DEFAULT_ID1) {
printf("read chip id failed!\r\n");
return ret;
}
/* reset 8311 to its default */
ret |= es8311_write_reg(ES8311_RESET_REG00, RST_DIG | RST_CMG | RST_MST | RST_ADC_DIG | RST_DAC_DIG);
bflb_mtimer_delay_ms(20);
ret |= es8311_write_reg(ES8311_RESET_REG00, 0x00);
ret |= es8311_write_reg(ES8311_RESET_REG00, CSM_ON); // power on cmd
// /* setup clock: source BCLK, polarities defaults, ADC and DAC clocks on */
// ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG01, MCLK_SEL | BCLK_ON | CLKADC_ON | CLKDAC_ON | ANACLKADC_ON | ANACLKDAC_ON);
// /* Frecuency config with BCLK = 32 * LRCK (automatic from uC frame) => IMCLK = 8 * BCLK
// * Simple math ==> IMCLK = (32 * 8 * LRCK) , where LRCK = Sample Rate*/
// ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG02, MULT_PRE | DIV_PRE);
// /* register ES8311_CLK_MANAGER_REG03 as default after POR */
// /* register ES8311_CLK_MANAGER_REG04 as default after POR */
// /* Oversampling as POR defaults on REG03 and REG04 */
// /* DIV_CLKADC=0 and DIV_CLKDAC=0 as defaults, but just for reasurement*/
// ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG05, DIV_CLKADC | DIV_CLKDAC);
// /* register ES8311_CLK_MANAGER_REG06 as default after POR */
// /* register ES8311_CLK_MANAGER_REG07 as default after POR */
// /* register ES8311_CLK_MANAGER_REG08 as default after POR */
// /**
// * REG06, REG07 and REG08 has no use in slave operation as DIV_BCLK and DIV_LRCK are disabled
// */
// /* Setup audio format (fmt): master/slave, resolution, I2S
// *
// * Beware, example code has a new reset on REG00 with 0xBF value
// * Not sure if needed here*/
// // ret |= es8311_write_reg(ES8311_RESET_REG00, 0xBF);
// /* Setup SDP In and Out resolution 16bits both */
// ret |= es8311_write_reg(ES8311_SDPIN_REG09, SDP_IN_WL_16BIT);
// ret |= es8311_write_reg(ES8311_SDPOUT_REG0A, SDP_IN_WL_16BIT);
// /**
// * SDP_IN_FMT (REG09 [1:0]) have a default value (00) so its config as I2S serial audio data format
// * Check if Left Justify is needed (01). Not sure about this
// *
// * Same with SDP_OUT_FMT
// *
// */
// ret |= es8311_write_reg(ES8311_SYSTEM_REG0D, REG_0D_DEFAULT); // Power up analog circuitry - NOT default
// ret |= es8311_write_reg(ES8311_SYSTEM_REG0E, REG_0E_DEFAULT); // Enable analog PGA, enable ADC modulator - NOT default
// ret |= es8311_write_reg(ES8311_SYSTEM_REG12, REG_12_DEFAULT); // power-up DAC - NOT default
// ret |= es8311_write_reg(ES8311_SYSTEM_REG13, HPSW); // Enable output to HP drive - NOT default
// ret |= es8311_write_reg(ES8311_ADC_REG1C, REG_1C_DEFAULT); // ADC Equalizer bypass, cancel DC offset in digital domain
// /* DAC ramprate and bypass DAC equalizer - NOT default */
// ret |= es8311_write_reg(ES8311_DAC_REG37, DAC_RAMPRATE_DEFAULT | DAC_EQBYPASS_DEFAULT);
// /* Set DAC Volume */
// ret |= es8311_write_reg(ES8311_DAC_REG32, DAC_VOL_PERCENT_LEVEL(80));
// /* Set ADC Volume */
// ret |= es8311_write_reg(ES8311_ADC_REG17, ADC_VOL_PERCENT_LEVEL(70));
// /* Set max PGA Gain for Mic (differential input) and turn DIG_MIC off */
// ret |= es8311_write_reg(ES8311_SYSTEM_REG14, LINSEL | PGAGAIN_15DB);
ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG01, 0x10);
ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG02, 0x00);
ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG03, 0x10);
ret |= es8311_write_reg(ES8311_ADC_REG16, 0x04);
ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG04, 0x10);
ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG05, 0x00);
ret |= es8311_write_reg(ES8311_SYSTEM_REG0B, 0x00);
ret |= es8311_write_reg(ES8311_SYSTEM_REG0C, 0x20);
ret |= es8311_write_reg(ES8311_SYSTEM_REG10, 0x13);
ret |= es8311_write_reg(ES8311_SYSTEM_REG11, 0x7C);
ret |= es8311_write_reg(ES8311_RESET_REG00, 0x80);
ret |= es8311_read_reg(ES8311_RESET_REG00, &read_data);
switch (i2s_cfg->mode) {
case ES8311_MODE_MASTER: /* MASTER MODE */
read_data |= 0x40;
break;
case ES8311_MODE_SLAVE: /* SLAVE MODE */
read_data &= 0xBF;
break;
default:
read_data &= 0xBF;
break;
}
ret |= es8311_write_reg(ES8311_RESET_REG00, read_data);
ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG01, 0x1F);
/* select clock source for internal mclk */
switch(get_es8311_mclk_src()) {
case FROM_MCLK_PIN:
ret |= es8311_read_reg(ES8311_CLK_MANAGER_REG01, &read_data);
read_data &= 0x7F;
ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG01, read_data);
break;
case FROM_SCLK_PIN:
ret |= es8311_read_reg(ES8311_CLK_MANAGER_REG01, &read_data);
read_data |= 0x80;
ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG01, read_data);
break;
default:
ret |= es8311_read_reg(ES8311_CLK_MANAGER_REG01, &read_data);
read_data &= 0x7F;
ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG01, read_data);
break;
}
int sample_fre = 0;
int mclk_fre = 0;
switch (i2s_cfg->samples) {
case ES8311_08K_SAMPLES:
sample_fre = 8000;
break;
case ES8311_11K_SAMPLES:
sample_fre = 11025;
break;
case ES8311_16K_SAMPLES:
sample_fre = 16000;
break;
case ES8311_22K_SAMPLES:
sample_fre = 22050;
break;
case ES8311_24K_SAMPLES:
sample_fre = 24000;
break;
case ES8311_32K_SAMPLES:
sample_fre = 32000;
break;
case ES8311_44K_SAMPLES:
sample_fre = 44100;
break;
case ES8311_48K_SAMPLES:
sample_fre = 48000;
break;
default:
printf("Unable to configure sample rate %dHz\r\n", sample_fre);
break;
}
mclk_fre = sample_fre * MCLK_DIV_FRE;
coeff = get_coeff(mclk_fre, sample_fre);
if (coeff < 0) {
printf("Unable to configure sample rate %dHz with %dHz MCLK\r\n", sample_fre, mclk_fre);
}
/*
* Set clock parammeters
*/
if (coeff >= 0) {
ret |= es8311_read_reg(ES8311_CLK_MANAGER_REG02, &read_data);
read_data &= 0x07;
read_data |= (coeff_div[coeff].pre_div - 1) << 5;
datmp = 0;
switch (coeff_div[coeff].pre_multi) {
case 1:
datmp = 0;
break;
case 2:
datmp = 1;
break;
case 4:
datmp = 2;
break;
case 8:
datmp = 3;
break;
default:
break;
}
if (get_es8311_mclk_src() == FROM_SCLK_PIN) {
datmp = 3; /* DIG_MCLK = LRCK * 256 = BCLK * 8 */
}
read_data |= (datmp) << 3;
ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG02, read_data);
ret |= es8311_read_reg(ES8311_CLK_MANAGER_REG05, &read_data);
read_data &= 0x00;
read_data |= (coeff_div[coeff].adc_div - 1) << 4;
read_data |= (coeff_div[coeff].dac_div - 1) << 0;
ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG05, read_data);
ret |= es8311_read_reg(ES8311_CLK_MANAGER_REG03, &read_data);
read_data &= 0x80;
read_data |= coeff_div[coeff].fs_mode << 6;
read_data |= coeff_div[coeff].adc_osr << 0;
ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG03, read_data);
ret = es8311_read_reg(ES8311_CLK_MANAGER_REG04, &read_data);
read_data &= 0x80;
read_data |= coeff_div[coeff].dac_osr << 0;
ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG04, read_data);
ret |= es8311_read_reg(ES8311_CLK_MANAGER_REG07, &read_data);
read_data &= 0xC0;
read_data |= coeff_div[coeff].lrck_h << 0;
ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG07, read_data);
ret |= es8311_read_reg(ES8311_CLK_MANAGER_REG08, &read_data);
read_data &= 0x00;
read_data |= coeff_div[coeff].lrck_l << 0;
ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG08, read_data);
ret |= es8311_read_reg(ES8311_CLK_MANAGER_REG06, &read_data);
read_data &= 0xE0;
if (coeff_div[coeff].bclk_div < 19) {
read_data |= (coeff_div[coeff].bclk_div - 1) << 0;
} else {
read_data |= (coeff_div[coeff].bclk_div) << 0;
}
ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG06, read_data);
}
/*
* mclk inverted or not
*/
if (INVERT_MCLK) {
ret |= es8311_read_reg(ES8311_CLK_MANAGER_REG01, &read_data);
read_data |= 0x40;
ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG01, read_data);
} else {
ret |= es8311_read_reg(ES8311_CLK_MANAGER_REG01, &read_data);
read_data &= ~(0x40);
ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG01, read_data);
}
/*
* sclk inverted or not
*/
if (INVERT_SCLK) {
ret |= es8311_read_reg(ES8311_CLK_MANAGER_REG06, &read_data);
read_data |= 0x20;
ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG06, read_data);
} else {
ret |= es8311_read_reg(ES8311_CLK_MANAGER_REG06, &read_data);
read_data &= ~(0x20);
ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG06, read_data);
}
ret |= es8311_write_reg(ES8311_SYSTEM_REG13, 0x10);
ret |= es8311_write_reg(ES8311_ADC_REG1B, 0x0A);
ret |= es8311_write_reg(ES8311_ADC_REG1C, 0x6A);
es8311_config_fmt(i2s_cfg->fmt);
es8311_set_bits_per_sample(i2s_cfg->bits);
// es8311_reg_dump();
return ret;
}
int es8311_codec_deinit(void)
{
return 0;
}
#ifndef BIT
#define BIT(nr) (1UL << (nr))
#endif
int es8311_start(es_module_t mode)
{
int ret = 0;
uint8_t adc_iface = 0, dac_iface = 0;
ret |= es8311_read_reg(ES8311_SDPIN_REG09, &dac_iface);
dac_iface &= 0xBF;
ret |= es8311_read_reg(ES8311_SDPOUT_REG0A, &adc_iface);
adc_iface &= 0xBF;
adc_iface |= BIT(6);
dac_iface |= BIT(6);
if (mode == ES_MODULE_LINE) {
return -1;
}
if (mode == ES_MODULE_ADC || mode == ES_MODULE_ADC_DAC) {
adc_iface &= ~(BIT(6));
}
if (mode == ES_MODULE_DAC || mode == ES_MODULE_ADC_DAC) {
dac_iface &= ~(BIT(6));
}
ret |= es8311_write_reg(ES8311_SDPIN_REG09, dac_iface);
ret |= es8311_write_reg(ES8311_SDPOUT_REG0A, adc_iface);
ret |= es8311_write_reg(ES8311_ADC_REG17, 0xBF);
ret |= es8311_write_reg(ES8311_SYSTEM_REG0E, 0x02);
ret |= es8311_write_reg(ES8311_SYSTEM_REG12, 0x00);
ret |= es8311_write_reg(ES8311_SYSTEM_REG14, 0x15);
/*
* pdm dmic enable or disable
*/
uint8_t regv = 0;
if (IS_DMIC) {
ret |= es8311_read_reg(ES8311_SYSTEM_REG14, &regv);
regv |= 0x40;
ret |= es8311_write_reg(ES8311_SYSTEM_REG14, regv);
} else {
ret |= es8311_read_reg(ES8311_SYSTEM_REG14, &regv);
regv &= ~(0x40);
ret |= es8311_write_reg(ES8311_SYSTEM_REG14, regv);
}
ret |= es8311_write_reg(ES8311_SYSTEM_REG0D, REG_0D_DEFAULT);
ret |= es8311_write_reg(ES8311_ADC_REG15, 0x40);
ret |= es8311_write_reg(ES8311_DAC_REG37, 0x48);
ret |= es8311_write_reg(ES8311_GP_REG45, 0x00);
/* set internal reference signal (ADCL + DACR) */
ret |= es8311_write_reg(ES8311_GPIO_REG44, 0x50);
// es8311_reg_dump();
return ret;
}
int es8311_stop(es_module_t mode)
{
int ret = 0;
es8311_suspend();
return ret;
}
int es8311_codec_set_voice_volume(int volume)
{
int res = 0;
if (volume < 0) {
volume = 0;
} else if (volume > 100) {
volume = 100;
}
int vol = (volume) * 2550 / 1000;
printf("SET: volume:%d%%\r\n", volume);
es8311_write_reg(ES8311_DAC_REG32, vol);
return res;
}
int es8311_codec_get_voice_volume(int *volume)
{
int ret = 0;
int regv = 0;
ret = es8311_read_reg(ES8311_DAC_REG32, &regv);
if (regv != 0) {
*volume = 0;
ret = -1;
} else {
*volume = regv * 100 / 256;
}
printf("GET: res:%d, volume:%d\r\n", regv, *volume);
return ret;
}
int es8311_set_voice_mute(bool enable)
{
int ret = 0;
printf("Es8311SetVoiceMute volume:%d\r\n", enable);
es8311_mute(enable);
return ret;
}
int es8311_get_voice_mute(int *mute)
{
int ret = 0;
uint8_t reg = 0;
ret = es8311_read_reg(ES8311_DAC_REG31, &reg);
if (ret == 0) {
reg = (ret & 0x20) >> 5;
}
*mute = reg;
return ret;
}
int es8311_set_mic_gain(i2s_es8311_mic_gain_t gain_db)
{
int res = 0;
res = es8311_write_reg(ES8311_ADC_REG16, gain_db); // MIC gain scale
return res;
}

View File

@ -0,0 +1,280 @@
/**
* @file bsp_es8311.h
* @brief
*
* Copyright (c) 2023 Bouffalolab team
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
*/
#ifndef __ES8311_H__
#define __ES8311_H__
typedef enum {
ES_MODULE_MIN = -1,
ES_MODULE_ADC = 0x01,
ES_MODULE_DAC = 0x02,
ES_MODULE_ADC_DAC = 0x03,
ES_MODULE_LINE = 0x04,
ES_MODULE_MAX
} es_module_t;
typedef enum {
ES8311_MODE_SLAVE = 0x00, /*!< set slave mode */
ES8311_MODE_MASTER = 0x01, /*!< set master mode */
} i2s_es8311_mode_t;
typedef enum {
ES8311_I2S_NORMAL = 0, /*!< set normal I2S format */
ES8311_I2S_LEFT, /*!< set all left format */
ES8311_I2S_RIGHT, /*!< set all right format */
ES8311_I2S_DSP, /*!< set dsp/pcm format */
} i2s_es8311_format_t;
typedef enum {
ES8311_08K_SAMPLES, /*!< set to 8k samples per second */
ES8311_11K_SAMPLES, /*!< set to 11.025k samples per second */
ES8311_16K_SAMPLES, /*!< set to 16k samples in per second */
ES8311_22K_SAMPLES, /*!< set to 22.050k samples per second */
ES8311_24K_SAMPLES, /*!< set to 24k samples in per second */
ES8311_32K_SAMPLES, /*!< set to 32k samples in per second */
ES8311_44K_SAMPLES, /*!< set to 44.1k samples per second */
ES8311_48K_SAMPLES, /*!< set to 48k samples per second */
} i2s_es8311_samples_t;
typedef enum {
ES8311_BIT_LENGTH_16BITS = 1, /*!< set 16 bits per sample */
ES8311_BIT_LENGTH_24BITS, /*!< set 24 bits per sample */
ES8311_BIT_LENGTH_32BITS, /*!< set 32 bits per sample */
} i2s_es8311_bits_t;
typedef enum {
ES8311_MIC_GAIN_MIN = -1,
ES8311_MIC_GAIN_0DB,
ES8311_MIC_GAIN_6DB,
ES8311_MIC_GAIN_12DB,
ES8311_MIC_GAIN_18DB,
ES8311_MIC_GAIN_24DB,
ES8311_MIC_GAIN_30DB,
ES8311_MIC_GAIN_36DB,
ES8311_MIC_GAIN_42DB,
ES8311_MIC_GAIN_MAX
} i2s_es8311_mic_gain_t;
typedef struct
{
i2s_es8311_mode_t mode; /*!< audio codec chip mode */
i2s_es8311_format_t fmt; /*!< I2S interface format */
i2s_es8311_samples_t samples; /*!< I2S interface samples per second */
i2s_es8311_bits_t bits; /*!< i2s interface number of bits per sample */
} i2s_es8311_t;
/******************************************************************************
* DEFINICIONES DE REGISTROS PARA ES8311
*****************************************************************************/
#define ES8311_RESET_REG00 0x00 /* reset digital,csm,clock manager etc.*/
#define ES8311_CLK_MANAGER_REG01 0x01 /* select clk src for mclk, enable clock for codec */
#define ES8311_CLK_MANAGER_REG02 0x02 /* clk divider and clk multiplier */
#define ES8311_CLK_MANAGER_REG03 0x03 /* adc fsmode and osr */
#define ES8311_CLK_MANAGER_REG04 0x04 /* dac osr */
#define ES8311_CLK_MANAGER_REG05 0x05 /* clk divier for adc and dac */
#define ES8311_CLK_MANAGER_REG06 0x06 /* bclk inverter and divider */
#define ES8311_CLK_MANAGER_REG07 0x07 /* tri-state, lrck divider */
#define ES8311_CLK_MANAGER_REG08 0x08 /* lrck divider */
#define ES8311_SDPIN_REG09 0x09 /* dac serial digital port */
#define ES8311_SDPOUT_REG0A 0x0A /* adc serial digital port */
#define ES8311_SYSTEM_REG0B 0x0B /* system */
#define ES8311_SYSTEM_REG0C 0x0C /* system */
#define ES8311_SYSTEM_REG0D 0x0D /* system, power up/down */
#define ES8311_SYSTEM_REG0E 0x0E /* system, power up/down */
#define ES8311_SYSTEM_REG0F 0x0F /* system, low power */
#define ES8311_SYSTEM_REG10 0x10 /* system */
#define ES8311_SYSTEM_REG11 0x11 /* system */
#define ES8311_SYSTEM_REG12 0x12 /* system, Enable DAC */
#define ES8311_SYSTEM_REG13 0x13 /* system */
#define ES8311_SYSTEM_REG14 0x14 /* system, select DMIC, select analog pga gain */
#define ES8311_ADC_REG15 0x15 /* ADC, adc ramp rate, dmic sense */
#define ES8311_ADC_REG16 0x16 /* ADC */
#define ES8311_ADC_REG17 0x17 /* ADC, volume */
#define ES8311_ADC_REG18 0x18 /* ADC, alc enable and winsize */
#define ES8311_ADC_REG19 0x19 /* ADC, alc maxlevel */
#define ES8311_ADC_REG1A 0x1A /* ADC, alc automute */
#define ES8311_ADC_REG1B 0x1B /* ADC, alc automute, adc hpf s1 */
#define ES8311_ADC_REG1C 0x1C /* ADC, equalizer, hpf s2 */
#define ES8311_DAC_REG31 0x31 /* DAC, mute */
#define ES8311_DAC_REG32 0x32 /* DAC, volume */
#define ES8311_DAC_REG33 0x33 /* DAC, offset */
#define ES8311_DAC_REG34 0x34 /* DAC, drc enable, drc winsize */
#define ES8311_DAC_REG35 0x35 /* DAC, drc maxlevel, minilevel */
#define ES8311_DAC_REG37 0x37 /* DAC, ramprate */
#define ES8311_GPIO_REG44 0x44 /* GPIO, dac2adc for test */
#define ES8311_GP_REG45 0x45 /* GP CONTROL */
#define ES8311_CHIP_ID1 0xFD /* CHIP ID1 */
#define ES8311_CHIP_ID2 0xFE /* CHIP ID2 */
#define ES8311_CHIP_VER 0xFF /* VERSION */
#define ES8311_MAX_REGISTER 0xFF
#define ES8311_DEFAULT_ID1 0x83
#define ES8311_DEFAULT_ID2 0x11
#define ES8311_DEFAULT_VER 0x00
/******************************************************************************
* DEFINICIONES DE BITS PARA ES8311
*****************************************************************************/
//------------------------- RESET REG 0x00 -----------------------------------
#define CSM_ON 0x80 //<--- Mask of CSM_ON bit
#define MSC 0x40 //<--- Mask of MSC bit
#define SEQ_DIS 0x20 //<--- Mask of SEQ_DIS bit
#define RST_DIG 0x10 //<--- Mask of RST_DIG bit
#define RST_CMG 0x08 //<--- Mask of RST_CMG bit
#define RST_MST 0x04 //<--- Mask of RST_MST bit
#define RST_ADC_DIG 0x02 //<--- Mask of RST_ADC_DIG bit
#define RST_DAC_DIG 0x01 //<--- Mask of RST_DAC_DIG bit
//------------------------- CLK MANAGER REG 0x01 -----------------------------
#define MCLK_SEL 0x80 //<--- Mask of MCLK_SEL bit
#define MCLK_INV 0x40 //<--- Mask of MCLK_INV bit
#define MCLK_ON 0x20 //<--- Mask of MCLK_ON bit
#define BCLK_ON 0x10 //<--- Mask of BCLK_ON bit
#define CLKADC_ON 0x08 //<--- Mask of CLKADC_ON bit
#define CLKDAC_ON 0x04 //<--- Mask of CLKDAC_ON bit
#define ANACLKADC_ON 0x02 //<--- Mask of ANACLKADC_ON bit
#define ANACLKDAC_ON 0x01 //<--- Mask of ANACLKDAC_ON bit
//------------------------- CLK MANAGER REG 0x06 -----------------------------
#define BCLK_CON 0x40 //<--- Mask of BCLK_CON bit
#define BCLK_INV 0x20 //<--- Mask of BCLK_INV bit
//Valid values for BCLK divider at Master mode DIV_BCLK[4:0]
#define DIV_BCLK_DEFAULT 0x03 //<--- Default value MCLK/4
#define DIV_BCLK_MCLK22 0x14 //<--- MCLK/22
#define DIV_BCLK_MCLK24 0x15 //<--- MCLK/24
#define DIV_BCLK_MCLK25 0x16 //<--- MCLK/25
#define DIV_BCLK_MCLK30 0x17 //<--- MCLK/30
#define DIV_BCLK_MCLK32 0x18 //<--- MCLK/32
#define DIV_BCLK_MCLK33 0x19 //<--- MCLK/33
#define DIV_BCLK_MCLK34 0x1A //<--- MCLK/34
#define DIV_BCLK_MCLK36 0x1B //<--- MCLK/36
#define DIV_BCLK_MCLK44 0x1C //<--- MCLK/44
#define DIV_BCLK_MCLK48 0x1D //<--- MCLK/48
#define DIV_BCLK_MCLK66 0x1E //<--- MCLK/66
#define DIV_BCLK_MCLK72 0x1F //<--- MCLK/72
//------------------------- SDP REG 0x09 -------------------------------------
/**
* NOTA: El software esta preparado para resolucion de 16 bits, asi que esa
* configuracion se hace hardcoded.
*/
#define SDP_IN_MUTE 0x40 //<--- Mask of SDP_IN_MUTE bit
#define SDP_IN_WL_16BIT 0x0C //<--- Value IN Word Length 16 bits
#define SDP_IN_FMT_LEFT 0x01 //<--- Value for left justify serial audio data format
//------------------------- SDP REG 0x0A -------------------------------------
/**
* NOTA: El software esta preparado para resolucion de 16 bits, asi que esa
* configuracion se hace hardcoded.
*/
#define SDP_OUT_MUTE 0x40 //<--- Mask of SDP_OUT_MUTE bit
#define SDP_OUT_WL_16BIT 0x0C //<--- Value OUT Word Length 16 bits
#define SDP_OUT_FMT_LEFT 0x01 //<--- Value for left justify serial audio data format
//------------------------- SYSTEM REG 0x0D ----------------------------------
#define REG_0D_DEFAULT 0x01 //<--- Value Start Up normal for automatic startup
//------------------------- SYSTEM REG 0x0E ----------------------------------
#define REG_0E_DEFAULT 0x02 //<--- Value for default startup
//------------------------- SYSTEM REG 0x12 ----------------------------------
#define REG_12_DEFAULT 0x00 //<--- Value for default startup
//------------------------- SYSTEM REG 0x13 ----------------------------------
#define HPSW 0x10 //<--- Mask of HPSW bit
//------------------------- SYSTEM REG 0x14 ----------------------------------
#define REG_14_DEFAULT 0x1A //<---- Value for max PGA gain and DMIC off
#define LINSEL 0x10 //<---- Value for Mic1p-1n select
#define PGAGAIN_0DB 0x00
#define PGAGAIN_3DB 0x01
#define PGAGAIN_6DB 0x02
#define PGAGAIN_9DB 0x03
#define PGAGAIN_12DB 0x04
#define PGAGAIN_15DB 0x05
#define PGAGAIN_18DB 0x06
#define PGAGAIN_21DB 0x07
#define PGAGAIN_24DB 0x08
#define PGAGAIN_27DB 0x09
#define PGAGAIN_30DB 0x0A
//------------------------- ADC REG 0x1C -------------------------------------
#define REG_1C_DEFAULT 0x6A //<--- Value for default startup
//------------------------ DAC VOL REG 0x32 ---------------------------------
#define DAC_VOLUME_0DB 0xBF //<--- 0 dB for DAC volume (not default)
//------------------------- DAC REG 0x37 -------------------------------------
#define DAC_RAMPRATE_DEFAULT 0x40 //<--- Value for 0.25dB/32LRCK
#define DAC_EQBYPASS_DEFAULT 0x08 //<--- Value for DAC_EQ bypass
/******************************************************************************
* DEFINICIONES ESPECIFICAS PARA UTILIZAR BCLK EN VEZ DE MCLK
*****************************************************************************/
/* INTERNAL MASTER CLOCK = 8 * BCLK */
#define MULT_PRE 0x18 //<--- Value mask for MULT_PRE = 8 bits [4:3]
#define DIV_PRE 0x00 //<--- Value mask for DIV_PRE = 0 bits [7:5]
#define DIV_CLKADC 0x00 //<--- Value mask for DIV_CLKADC = 0 bits [7:4]
#define DIV_CLKDAC 0x00 //<--- Value mask for DIV_CLKDAC = 0 bits [3:0]
/**
* @brief This is a translation of volume levels from percentage to uint8_t
*
* The volume of DAC goes in steps of 0.5dB from -95.5dB to +32dB
* This function translates a percentage to a decimal value of one byte
* corresponding to a level as Datasheets shows
*/
#define DAC_VOL_PERCENT_LEVEL(x) ((255 * x) / 100)
#define ADC_VOL_PERCENT_LEVEL(x) DAC_VOL_PERCENT_LEVEL(x)
int es8311_init(i2s_es8311_t *i2s_cfg);
int es8311_start(es_module_t mode);
int es8311_stop(es_module_t mode);
int es8311_codec_set_voice_volume(int volume);
int es8311_codec_get_voice_volume(int *volume);
int es8311_set_voice_mute(bool enable);
int es8311_get_voice_mute(int *mute);
int es8311_set_mic_gain(i2s_es8311_mic_gain_t gain_db);
#endif /* __ES8311_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,12 @@
[cfg]
# 0: no erase, 1:programmed section erase, 2: chip erase
erase = 1
# skip mode set first para is skip addr, second para is skip len, multi-segment region with ; separated
skip_mode = 0x0, 0x0
# 0: not use isp mode, #1: isp mode
boot2_isp_mode = 0
[FW]
filedir = ./build/build_out/i2s*_$(CHIPNAME).bin
address = 0x000000

View File

@ -0,0 +1,254 @@
/**
* @file main.c
* @brief
*
* Copyright (c) 2023 Bouffalolab team
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
*
*/
#include "board.h"
#include "bflb_gpio.h"
#include "bflb_l1c.h"
#include "bflb_mtimer.h"
#include "bflb_i2c.h"
#include "bl616_glb.h"
#include "bflb_dma.h"
#include "bsp_es8311.h"
#include "bflb_i2s.h"
#include "fhm_onechannel_16k_20.h"
// 8311
struct bflb_device_s *i2s0;
struct bflb_device_s *dma0_ch0;
struct bflb_device_s *dma0_ch1;
ATTR_NOCACHE_RAM_SECTION uint8_t rx_buffer[16000];
void dma0_ch0_isr(void *arg)
{
printf("tc done\r\n");
}
void dma0_ch1_isr(void *arg)
{
printf("rx done\r\n");\
}
void i2s_gpio_init()
{
struct bflb_device_s *gpio;
gpio = bflb_device_get_by_name("gpio");
/* I2S_FS */
bflb_gpio_init(gpio, GPIO_PIN_13, GPIO_FUNC_I2S | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
/* I2S_DI */
bflb_gpio_init(gpio, GPIO_PIN_14, GPIO_FUNC_I2S | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
/* I2S_DO */
bflb_gpio_init(gpio, GPIO_PIN_15, GPIO_FUNC_I2S | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
/* I2S_BCLK */
bflb_gpio_init(gpio, GPIO_PIN_20, GPIO_FUNC_I2S | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
// /* MCLK CLKOUT */
// bflb_gpio_init(gpio, GPIO_PIN_23, GPIO_FUNC_CLKOUT | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2);
/* I2C0_SCL */
bflb_gpio_init(gpio, GPIO_PIN_10, GPIO_FUNC_I2C0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2);
/* I2C0_SDA */
bflb_gpio_init(gpio, GPIO_PIN_11, GPIO_FUNC_I2C0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2);
}
// void i2s_dma_init()
// {
// static struct bflb_dma_channel_lli_pool_s tx_llipool[100];
// static struct bflb_dma_channel_lli_transfer_s tx_transfers[1];
// struct bflb_i2s_config_s i2s_cfg = {
// .bclk_freq_hz = 16000 * 32 * 2, /* bclk = Sampling_rate * frame_width * channel_num */
// .role = I2S_ROLE_MASTER,
// .format_mode = I2S_MODE_LEFT_JUSTIFIED,
// .channel_mode = I2S_CHANNEL_MODE_NUM_1,
// .frame_width = I2S_SLOT_WIDTH_32,
// .data_width = I2S_SLOT_WIDTH_16,
// .fs_offset_cycle = 0,
// .tx_fifo_threshold = 0,
// .rx_fifo_threshold = 0,
// };
// struct bflb_dma_channel_config_s tx_config = {
// .direction = DMA_MEMORY_TO_PERIPH,
// .src_req = DMA_REQUEST_NONE,
// .dst_req = DMA_REQUEST_I2S_TX,
// .src_addr_inc = DMA_ADDR_INCREMENT_ENABLE,
// .dst_addr_inc = DMA_ADDR_INCREMENT_DISABLE,
// .src_burst_count = DMA_BURST_INCR1,
// .dst_burst_count = DMA_BURST_INCR1,
// .src_width = DMA_DATA_WIDTH_16BIT,
// .dst_width = DMA_DATA_WIDTH_16BIT,
// };
// printf("i2s init\r\n");
// i2s0 = bflb_device_get_by_name("i2s0");
// /* i2s init */
// bflb_i2s_init(i2s0, &i2s_cfg);
// /* enable dma */
// bflb_i2s_link_txdma(i2s0, true);
// bflb_i2s_link_rxdma(i2s0, true);
// printf("dma init\r\n");
// dma0_ch0 = bflb_device_get_by_name("dma0_ch0");
// bflb_dma_channel_init(dma0_ch0, &tx_config);
// bflb_dma_channel_irq_attach(dma0_ch0, dma0_ch0_isr, NULL);
// tx_transfers[0].src_addr = (uint32_t)fhm_onechannel_16k_20;
// tx_transfers[0].dst_addr = (uint32_t)DMA_ADDR_I2S_TDR;
// tx_transfers[0].nbytes = sizeof(fhm_onechannel_16k_20);
// printf("dma lli init\r\n");
// uint32_t num = bflb_dma_channel_lli_reload(dma0_ch0, tx_llipool, 100, tx_transfers, 1);
// bflb_dma_channel_lli_link_head(dma0_ch0, tx_llipool, num);
// printf("dma lli num: %d \r\n", num);
// bflb_dma_channel_start(dma0_ch0);
// }
void i2s_dma_init()
{
static struct bflb_dma_channel_lli_pool_s tx_llipool[100];
static struct bflb_dma_channel_lli_transfer_s tx_transfers[1];
static struct bflb_dma_channel_lli_pool_s rx_llipool[100];
static struct bflb_dma_channel_lli_transfer_s rx_transfers[1];
struct bflb_i2s_config_s i2s_cfg = {
.bclk_freq_hz = 16000 * 16 * 2, /* bclk = Sampling_rate * frame_width * channel_num */
.role = I2S_ROLE_MASTER,
.format_mode = I2S_MODE_LEFT_JUSTIFIED,
.channel_mode = I2S_CHANNEL_MODE_NUM_2,
.frame_width = I2S_SLOT_WIDTH_16,
.data_width = I2S_SLOT_WIDTH_16,
.fs_offset_cycle = 0,
.tx_fifo_threshold = 0,
.rx_fifo_threshold = 0,
};
struct bflb_dma_channel_config_s tx_config = {
.direction = DMA_MEMORY_TO_PERIPH,
.src_req = DMA_REQUEST_NONE,
.dst_req = DMA_REQUEST_I2S_TX,
.src_addr_inc = DMA_ADDR_INCREMENT_ENABLE,
.dst_addr_inc = DMA_ADDR_INCREMENT_DISABLE,
.src_burst_count = DMA_BURST_INCR1,
.dst_burst_count = DMA_BURST_INCR1,
.src_width = DMA_DATA_WIDTH_16BIT,
.dst_width = DMA_DATA_WIDTH_16BIT,
};
struct bflb_dma_channel_config_s rx_config = {
.direction = DMA_PERIPH_TO_MEMORY,
.src_req = DMA_REQUEST_I2S_RX,
.dst_req = DMA_REQUEST_NONE,
.src_addr_inc = DMA_ADDR_INCREMENT_DISABLE,
.dst_addr_inc = DMA_ADDR_INCREMENT_ENABLE,
.src_burst_count = DMA_BURST_INCR1,
.dst_burst_count = DMA_BURST_INCR1,
.src_width = DMA_DATA_WIDTH_16BIT,
.dst_width = DMA_DATA_WIDTH_16BIT
};
printf("i2s init\r\n");
i2s0 = bflb_device_get_by_name("i2s0");
/* i2s init */
bflb_i2s_init(i2s0, &i2s_cfg);
/* enable dma */
bflb_i2s_link_txdma(i2s0, true);
bflb_i2s_link_rxdma(i2s0, true);
printf("dma init\r\n");
dma0_ch0 = bflb_device_get_by_name("dma0_ch0");
dma0_ch1 = bflb_device_get_by_name("dma0_ch1");
bflb_dma_channel_init(dma0_ch0, &tx_config);
bflb_dma_channel_init(dma0_ch1, &rx_config);
bflb_dma_channel_irq_attach(dma0_ch0, dma0_ch0_isr, NULL);
bflb_dma_channel_irq_attach(dma0_ch1, dma0_ch1_isr, NULL);
tx_transfers[0].src_addr = (uint32_t)rx_buffer;
tx_transfers[0].dst_addr = (uint32_t)DMA_ADDR_I2S_TDR;
tx_transfers[0].nbytes = sizeof(rx_buffer);
rx_transfers[0].src_addr = (uint32_t)DMA_ADDR_I2S_RDR;
rx_transfers[0].dst_addr = (uint32_t)rx_buffer;
rx_transfers[0].nbytes = sizeof(rx_buffer);
printf("dma lli init\r\n");
uint32_t num = bflb_dma_channel_lli_reload(dma0_ch0, tx_llipool, 100, tx_transfers, 1);
bflb_dma_channel_lli_link_head(dma0_ch0, tx_llipool, num);
printf("tx dma lli num: %d \r\n", num);
num = bflb_dma_channel_lli_reload(dma0_ch1, rx_llipool, 100, rx_transfers, 1);
printf("rx dma lli num: %d \r\n", num);
bflb_dma_channel_lli_link_head(dma0_ch1, rx_llipool, num);
bflb_dma_channel_start(dma0_ch0);
bflb_dma_channel_start(dma0_ch1);
}
void mclk_out_init()
{
/* output MCLK,
Will change the clock source of i2s,
It needs to be called before i2s is initialized
clock source 25M
*/
GLB_Set_I2S_CLK(ENABLE, 0, GLB_I2S_DI_SEL_I2S_DI_INPUT, GLB_I2S_DO_SEL_I2S_DO_OUTPT);
/* ES8311 do not mclk */
// GLB_Set_Chip_Clock_Out3_Sel(GLB_CHIP_CLK_OUT_3_I2S_REF_CLK);
}
int main(void)
{
board_init();
/* gpio init */
i2s_gpio_init();
/* mclk clkout init */
mclk_out_init();
i2s_es8311_t es8311_cfg;
es8311_cfg.mode = ES8311_MODE_SLAVE;
es8311_cfg.fmt = ES8311_I2S_NORMAL;
es8311_cfg.samples = ES8311_16K_SAMPLES;
es8311_cfg.bits = ES8311_BIT_LENGTH_16BITS;
/* init ES8311 Codec */
printf("es8311 init\n\r");
es8311_init(&es8311_cfg);
es8311_codec_set_voice_volume(70);
es8311_start(ES_MODULE_ADC_DAC);
/* i2s init */
i2s_dma_init();
/* enable i2s tx and rx */
bflb_i2s_feature_control(i2s0, I2S_CMD_DATA_ENABLE, I2S_CMD_DATA_ENABLE_TX | I2S_CMD_DATA_ENABLE_RX);
while (1) {
bflb_mtimer_delay_ms(10);
}
}

View File

@ -0,0 +1 @@
#set(CONFIG_XXX 1)

View File

@ -0,0 +1,10 @@
cmake_minimum_required(VERSION 3.15)
include(proj.conf)
find_package(bouffalo_sdk REQUIRED HINTS $ENV{BL_SDK_BASE})
target_sources(app PRIVATE jpeg_head.c)
sdk_set_main_file(main.c)
project(mjpeg_cam_crop)

View File

@ -0,0 +1,13 @@
SDK_DEMO_PATH ?= .
BL_SDK_BASE ?= $(SDK_DEMO_PATH)/../../../..
export BL_SDK_BASE
CHIP ?= bl616
BOARD ?= bl616dk
CROSS_COMPILE ?= riscv64-unknown-elf-
# add custom cmake definition
#cmake_definition+=-Dxxx=sss
include $(BL_SDK_BASE)/project.build

View File

@ -0,0 +1,43 @@
# mjpeg_cam_crop
## Support CHIP
| CHIP | Remark |
|:----------------:|:------:|
|BL702/BL704/BL706 | |
|BL616/BL618 | |
|BL808 | |
## Compile
- BL602/BL604
```
make CHIP=bl602 BOARD=bl602dk
```
- BL702/BL704/BL706
```
make CHIP=bl702 BOARD=bl702dk
```
- BL616/BL618
```
make CHIP=bl616 BOARD=bl616dk
```
- BL808
```
make CHIP=bl808 BOARD=bl808dk CPU_ID=m0
make CHIP=bl808 BOARD=bl808dk CPU_ID=d0
```
## Flash
```
make flash CHIP=chip_name COMX=xxx # xxx is your com name
```

View File

@ -0,0 +1,11 @@
[cfg]
# 0: no erase, 1:programmed section erase, 2: chip erase
erase = 1
# skip mode set first para is skip addr, second para is skip len, multi-segment region with ; separated
skip_mode = 0x0, 0x0
# 0: not use isp mode, #1: isp mode
boot2_isp_mode = 0
[FW]
filedir = ./build/build_out/mjpeg*_$(CHIPNAME).bin
address = 0x000000

View File

@ -0,0 +1,185 @@
#include "jpeg_head.h"
static const uint8_t tableQy[] = {
16, 11, 12, 14, 12, 10, 16, 14,
13, 14, 18, 17, 16, 19, 24, 40,
26, 24, 22, 22, 24, 49, 35, 37,
29, 40, 58, 51, 61, 60, 57, 51,
56, 55, 64, 72, 92, 78, 64, 68,
87, 69, 55, 56, 80, 109, 81, 87,
95, 98, 103, 104, 103, 62, 77, 113,
121, 112, 100, 120, 92, 101, 103, 99
};
static const uint8_t tableQuv[] = {
17, 18, 18, 24, 21, 24, 47, 26,
26, 47, 99, 66, 56, 66, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99
};
static const uint8_t tableHuffman[] = {
0xFF, 0xC4, 0x00, 0x1F, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,
0x0B,
0xFF, 0xC4, 0x00, 0xB5, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04,
0x04, 0x00, 0x00, 0x01, 0x7D, 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41,
0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08, 0x23, 0x42, 0xB1,
0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17, 0x18, 0x19,
0x1A, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44,
0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64,
0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x83, 0x84,
0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2,
0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9,
0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7,
0xD8, 0xD9, 0xDA, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3,
0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA,
0xFF, 0xC4, 0x00, 0x1F, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,
0x0B,
0xFF, 0xC4, 0x00, 0xB5, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04,
0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12,
0x41, 0x51, 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xA1, 0xB1, 0xC1,
0x09, 0x23, 0x33, 0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16, 0x24, 0x34, 0xE1, 0x25, 0xF1,
0x17, 0x18, 0x19, 0x1A, 0x26, 0x27, 0x28, 0x29, 0X2A, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43,
0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63,
0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x82,
0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7,
0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5,
0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF2, 0xF3,
0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA
};
static void QCalc(const uint8_t *in, uint8_t *out, uint8_t q)
{
float tq, result;
int i;
if (q < 1)
tq = 5000.0f;
else if (q <= 50)
tq = 5000.0f / q;
else if (q <= 100)
tq = 200.0f - 2.0f * q;
else
tq = 0.0f;
tq = tq / 100.0f;
for (i = 0; i < 64; i++) {
result = in[i] * tq;
if (result > 255.0f)
out[i] = 255;
else if (result < 1.0f)
out[i] = 1;
else
out[i] = (uint8_t)(result + 0.5f);
}
}
uint32_t JpegHeadCreate(uint8_t type, uint8_t q, int width, int height, uint8_t *out)
{
uint32_t index = 0;
uint32_t i;
/* start of jpeg file */
out[index++] = 0xFF;
out[index++] = 0xD8;
/* define quality table */
out[index++] = 0xFF;
out[index++] = 0xDB;
out[index++] = 0x00;
out[index++] = 0x43; //=3+N, N=64
out[index++] = 0x00;
QCalc(tableQy, out + index, q); //Y quality table
index += 64;
out[index++] = 0xFF;
out[index++] = 0xDB;
out[index++] = 0x00;
out[index++] = 0x43; //=3+N, N=64
out[index++] = 0x01;
QCalc(tableQuv, out + index, q); //UV quality table
index += 64;
/* basic information of mjpeg */
out[index++] = 0xFF;
out[index++] = 0xC0;
out[index++] = 0x00;
if (type == YUV_MODE_400)
out[index++] = 0x0B; //length:2 + bits:1 + height:2 + width:2 + num:1 + 3 * part=1
else
out[index++] = 0x11; //length:2 + bits:1 + height:2 + width:2 + num:1 + 3 * part=3
out[index++] = 0x08;
out[index++] = (uint8_t)((height >> 8) & 0xFF);
out[index++] = (uint8_t)(height & 0xFF);
out[index++] = (uint8_t)((width >> 8) & 0xFF);
out[index++] = (uint8_t)(width & 0xFF);
if (type == YUV_MODE_400) {
out[index++] = 0x01; //number of part
out[index++] = 0x01; //the first part id
out[index++] = 0x11; //[0:3]vertical sample coefficient, [4:7]horizontal sample coefficient
out[index++] = 0x00; //id of quality tab
} else if (type == YUV_MODE_420) {
out[index++] = 0x03; //number of part
out[index++] = 0x01; //the first part id
out[index++] = 0x22; //[0:3]vertical sample coefficient, [4:7]horizontal sample coefficient
out[index++] = 0x00; //id of quality tab
out[index++] = 0x02; //the second part id
out[index++] = 0x11; //[0:3]vertical sample coefficient, [4:7]horizontal sample coefficient
out[index++] = 0x01; //id of quality tab
out[index++] = 0x03; //the third part id
out[index++] = 0x11; //[0:3]vertical sample coefficient, [4:7]horizontal sample coefficient
out[index++] = 0x01; //id of quality tab
} else if (type == YUV_MODE_422) {
out[index++] = 0x03; //number of part
out[index++] = 0x01; //the first part id
out[index++] = 0x21; //[0:3]vertical sample coefficient, [4:7]horizontal sample coefficient
out[index++] = 0x00; //id of quality tab
out[index++] = 0x02; //the second part id
out[index++] = 0x11; //[0:3]vertical sample coefficient, [4:7]horizontal sample coefficient
out[index++] = 0x01; //id of quality tab
out[index++] = 0x03; //the third part id
out[index++] = 0x11; //[0:3]vertical sample coefficient, [4:7]horizontal sample coefficient
out[index++] = 0x01; //id of quality tab
}
/* define Huffman table */
for (i = 0; i < sizeof(tableHuffman); i++) {
out[index++] = tableHuffman[i];
}
/* start of scan*/
out[index++] = 0xFF;
out[index++] = 0xDA;
if (type == YUV_MODE_400) {
out[index++] = 0x00;
out[index++] = 0x08; //length
out[index++] = 0x01;
out[index++] = 0x01;
out[index++] = 0x00;
out[index++] = 0x02;
out[index++] = 0x3F;
out[index++] = 0x00;
} else {
out[index++] = 0x00;
out[index++] = 0x0C; //length
out[index++] = 0x03;
out[index++] = 0x01;
out[index++] = 0x00;
out[index++] = 0x02;
out[index++] = 0x11;
out[index++] = 0x03;
out[index++] = 0x11;
out[index++] = 0x00;
out[index++] = 0x3F;
out[index++] = 0x00;
}
return index;
}

View File

@ -0,0 +1,12 @@
#ifndef __JPEG_HEAD_H__
#define __JPEG_HEAD_H__
#include "stdint.h"
#define YUV_MODE_400 1
#define YUV_MODE_420 2
#define YUV_MODE_422 3
extern uint32_t JpegHeadCreate(uint8_t type, uint8_t q, int width, int height, uint8_t *out);
#endif /* __JPEG_HEAD_H__ */

View File

@ -0,0 +1,150 @@
#include "bflb_mtimer.h"
#include "bflb_i2c.h"
#include "bflb_cam.h"
#include "bflb_mjpeg.h"
#include "image_sensor.h"
#include "board.h"
#include "jpeg_head.h"
#define BLOCK_NUM 2
#define ROW_NUM (8 * BLOCK_NUM)
#define CAM_FRAME_COUNT_USE 5
#define CROP_WQVGA_X 416
#define CROP_WQVGA_Y 240
static struct bflb_device_s *i2c0;
static struct bflb_device_s *cam0;
static struct bflb_device_s *mjpeg;
volatile uint32_t pic_count = 0;
volatile uint32_t pic_addr[CAM_FRAME_COUNT_USE] = { 0 };
volatile uint32_t pic_len[CAM_FRAME_COUNT_USE] = { 0 };
static __attribute__((aligned(32))) ATTR_NOINIT_PSRAM_SECTION uint8_t dvp_buffer[CROP_WQVGA_X * 2 * ROW_NUM];
static __attribute__((aligned(32))) ATTR_NOINIT_PSRAM_SECTION uint8_t mjpeg_buffer[50 * 1024 * CAM_FRAME_COUNT_USE];
void mjpeg_isr(int irq, void *arg)
{
uint8_t *pic;
uint32_t jpeg_len;
uint32_t intstatus = bflb_mjpeg_get_intstatus(mjpeg);
if (intstatus & MJPEG_INTSTS_ONE_FRAME) {
bflb_mjpeg_int_clear(mjpeg, MJPEG_INTCLR_ONE_FRAME);
jpeg_len = bflb_mjpeg_get_frame_info(mjpeg, &pic);
pic_addr[pic_count] = (uint32_t)pic;
pic_len[pic_count] = jpeg_len;
pic_count++;
bflb_mjpeg_pop_one_frame(mjpeg);
if (pic_count == CAM_FRAME_COUNT_USE) {
bflb_cam_stop(cam0);
bflb_mjpeg_stop(mjpeg);
}
}
}
uint8_t jpg_head_buf[800] = { 0 };
uint32_t jpg_head_len;
uint8_t MJPEG_QUALITY = 50;
#define SIZE_BUFFER (4 * 1024 * 1024)
void bflb_mjpeg_dump_hex(uint8_t *data, uint32_t len)
{
uint32_t i = 0;
for (i = 0; i < len; i++) {
if (i % 16 == 0) {
printf("\r\n");
}
printf("%02x ", data[i]);
}
printf("\r\n");
}
int main(void)
{
struct bflb_cam_config_s cam_config;
struct image_sensor_config_s *sensor_config;
board_init();
board_dvp_gpio_init();
i2c0 = bflb_device_get_by_name("i2c0");
cam0 = bflb_device_get_by_name("cam0");
if (image_sensor_scan(i2c0, &sensor_config)) {
printf("\r\nSensor name: %s\r\n", sensor_config->name);
} else {
printf("\r\nError! Can't identify sensor!\r\n");
while (1) {
}
}
/* Crop resolution_x, should be set before init */
bflb_cam_crop_hsync(cam0, 112, 112 + CROP_WQVGA_X);
/* Crop resolution_y, should be set before init */
bflb_cam_crop_vsync(cam0, 120, 120 + CROP_WQVGA_Y);
memcpy(&cam_config, sensor_config, IMAGE_SENSOR_INFO_COPY_SIZE);
cam_config.with_mjpeg = true;
cam_config.input_source = CAM_INPUT_SOURCE_DVP;
cam_config.output_format = CAM_OUTPUT_FORMAT_AUTO;
cam_config.output_bufaddr = (uint32_t)dvp_buffer;
cam_config.output_bufsize = CROP_WQVGA_X * 2 * ROW_NUM;
bflb_cam_init(cam0, &cam_config);
bflb_cam_start(cam0);
cam_config.resolution_x = CROP_WQVGA_X;
cam_config.resolution_y = CROP_WQVGA_Y;
mjpeg = bflb_device_get_by_name("mjpeg");
struct bflb_mjpeg_config_s config;
config.format = MJPEG_FORMAT_YUV422_YUYV;
config.quality = MJPEG_QUALITY;
config.rows = ROW_NUM;
config.resolution_x = cam_config.resolution_x;
config.resolution_y = cam_config.resolution_y;
config.input_bufaddr0 = (uint32_t)dvp_buffer;
config.input_bufaddr1 = 0;
config.output_bufaddr = (uint32_t)mjpeg_buffer;
config.output_bufsize = sizeof(mjpeg_buffer);
config.input_yy_table = NULL; /* use default table */
config.input_uv_table = NULL; /* use default table */
bflb_mjpeg_init(mjpeg, &config);
jpg_head_len = JpegHeadCreate(YUV_MODE_422, MJPEG_QUALITY, cam_config.resolution_x, cam_config.resolution_y, jpg_head_buf);
bflb_mjpeg_fill_jpeg_header_tail(mjpeg, jpg_head_buf, jpg_head_len);
bflb_mjpeg_tcint_mask(mjpeg, false);
bflb_irq_attach(mjpeg->irq_num, mjpeg_isr, NULL);
bflb_irq_enable(mjpeg->irq_num);
bflb_mjpeg_start(mjpeg);
while (pic_count < CAM_FRAME_COUNT_USE) {
printf("pic count:%d\r\n", pic_count);
bflb_mtimer_delay_ms(200);
}
for (uint8_t i = 0; i < CAM_FRAME_COUNT_USE; i++) {
if ((pic_addr[i] + pic_len[i]) > ((uint32_t)mjpeg_buffer + sizeof(mjpeg_buffer))) {
printf("drop invalid pic\r\n");
continue;
}
printf("jpg addr:%08x ,jpg size:%d\r\n", pic_addr[i], pic_len[i]);
// bflb_mjpeg_dump_hex((uint8_t *)pic_addr[i], pic_len[i]);
}
while (1) {
bflb_mtimer_delay_ms(1000);
}
}

View File

@ -0,0 +1,2 @@
set(CONFIG_BSP_IMAGE_SENSOR 1)
set(CONFIG_PSRAM 1)

View File

@ -0,0 +1,12 @@
cmake_minimum_required(VERSION 3.15)
include(proj.conf)
find_package(bouffalo_sdk REQUIRED HINTS $ENV{BL_SDK_BASE})
sdk_add_include_directories(.)
target_sources(app PRIVATE cdc_acm_msc_template.c)
sdk_set_main_file(main.c)
project(usbd_cdc_acm_msc)

View File

@ -0,0 +1,13 @@
SDK_DEMO_PATH ?= .
BL_SDK_BASE ?= $(SDK_DEMO_PATH)/../../../..
export BL_SDK_BASE
CHIP ?= bl616
BOARD ?= bl616dk
CROSS_COMPILE ?= riscv64-unknown-elf-
# add custom cmake definition
#cmake_definition+=-Dxxx=sss
include $(BL_SDK_BASE)/project.build

View File

@ -0,0 +1,37 @@
# usbd_cdc_acm_msc
## Support CHIP
| CHIP | Remark |
|:----------------:|:------:|
|BL702/BL704/BL706 | |
|BL616/BL618 | |
|BL808 | D0 has no irq |
## Compile
- BL702/BL704/BL706
```
make CHIP=bl702 BOARD=bl702dk
```
- BL616/BL618
```
make CHIP=bl616 BOARD=bl616dk
```
- BL808
```
make CHIP=bl808 BOARD=bl808dk CPU_ID=m0
make CHIP=bl808 BOARD=bl808dk CPU_ID=d0
```
## Flash
```
make flash CHIP=chip_name COMX=xxx # xxx is your com name
```

View File

@ -0,0 +1,250 @@
#include "usbd_core.h"
#include "usbd_cdc.h"
#include "usbd_msc.h"
/*!< endpoint address */
#define CDC_IN_EP 0x81
#define CDC_OUT_EP 0x02
#define CDC_INT_EP 0x86
#define MSC_IN_EP 0x83
#define MSC_OUT_EP 0x04
#define USBD_VID 0xFFFF
#define USBD_PID 0xFFFF
#define USBD_MAX_POWER 100
#define USBD_LANGID_STRING 1033
/*!< config descriptor size */
#define USB_CONFIG_SIZE (9 + CDC_ACM_DESCRIPTOR_LEN + MSC_DESCRIPTOR_LEN)
#ifdef CONFIG_USB_HS
#define CDC_MAX_MPS 512
#else
#define CDC_MAX_MPS 64
#endif
#ifdef CONFIG_USB_HS
#define MSC_MAX_MPS 512
#else
#define MSC_MAX_MPS 64
#endif
/*!< global descriptor */
static const uint8_t cdc_msc_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01),
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x03, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, 0x02),
MSC_DESCRIPTOR_INIT(0x02, MSC_OUT_EP, MSC_IN_EP, MSC_MAX_MPS, 0x00),
///////////////////////////////////////
/// string0 descriptor
///////////////////////////////////////
USB_LANGID_INIT(USBD_LANGID_STRING),
///////////////////////////////////////
/// string1 descriptor
///////////////////////////////////////
0x14, /* bLength */
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
'C', 0x00, /* wcChar0 */
'h', 0x00, /* wcChar1 */
'e', 0x00, /* wcChar2 */
'r', 0x00, /* wcChar3 */
'r', 0x00, /* wcChar4 */
'y', 0x00, /* wcChar5 */
'U', 0x00, /* wcChar6 */
'S', 0x00, /* wcChar7 */
'B', 0x00, /* wcChar8 */
///////////////////////////////////////
/// string2 descriptor
///////////////////////////////////////
0x26, /* bLength */
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
'C', 0x00, /* wcChar0 */
'h', 0x00, /* wcChar1 */
'e', 0x00, /* wcChar2 */
'r', 0x00, /* wcChar3 */
'r', 0x00, /* wcChar4 */
'y', 0x00, /* wcChar5 */
'U', 0x00, /* wcChar6 */
'S', 0x00, /* wcChar7 */
'B', 0x00, /* wcChar8 */
' ', 0x00, /* wcChar9 */
'C', 0x00, /* wcChar10 */
'-', 0x00, /* wcChar11 */
'M', 0x00, /* wcChar12 */
' ', 0x00, /* wcChar13 */
'D', 0x00, /* wcChar14 */
'E', 0x00, /* wcChar15 */
'M', 0x00, /* wcChar16 */
'O', 0x00, /* wcChar17 */
///////////////////////////////////////
/// string3 descriptor
///////////////////////////////////////
0x16, /* bLength */
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
'2', 0x00, /* wcChar0 */
'0', 0x00, /* wcChar1 */
'2', 0x00, /* wcChar2 */
'2', 0x00, /* wcChar3 */
'1', 0x00, /* wcChar4 */
'2', 0x00, /* wcChar5 */
'3', 0x00, /* wcChar6 */
'4', 0x00, /* wcChar7 */
'5', 0x00, /* wcChar8 */
'6', 0x00, /* wcChar9 */
#ifdef CONFIG_USB_HS
///////////////////////////////////////
/// device qualifier descriptor
///////////////////////////////////////
0x0a,
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x02,
0x02,
0x01,
0x40,
0x01,
0x00,
#endif
0x00
};
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[2048];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[2048];
volatile bool ep_tx_busy_flag = false;
#ifdef CONFIG_USB_HS
#define CDC_MAX_MPS 512
#else
#define CDC_MAX_MPS 64
#endif
void usbd_event_handler(uint8_t event)
{
switch (event) {
case USBD_EVENT_RESET:
break;
case USBD_EVENT_CONNECTED:
break;
case USBD_EVENT_DISCONNECTED:
break;
case USBD_EVENT_RESUME:
break;
case USBD_EVENT_SUSPEND:
break;
case USBD_EVENT_CONFIGURED:
/* setup first out ep read transfer */
usbd_ep_start_read(CDC_OUT_EP, read_buffer, 2048);
break;
case USBD_EVENT_SET_REMOTE_WAKEUP:
break;
case USBD_EVENT_CLR_REMOTE_WAKEUP:
break;
default:
break;
}
}
void usbd_cdc_acm_bulk_out(uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
/* setup next out ep read transfer */
usbd_ep_start_read(CDC_OUT_EP, read_buffer, 2048);
}
void usbd_cdc_acm_bulk_in(uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual in len:%d\r\n", nbytes);
if ((nbytes % CDC_MAX_MPS) == 0 && nbytes) {
/* send zlp */
usbd_ep_start_write(CDC_IN_EP, NULL, 0);
} else {
ep_tx_busy_flag = false;
}
}
/*!< endpoint call back */
struct usbd_endpoint cdc_out_ep = {
.ep_addr = CDC_OUT_EP,
.ep_cb = usbd_cdc_acm_bulk_out
};
struct usbd_endpoint cdc_in_ep = {
.ep_addr = CDC_IN_EP,
.ep_cb = usbd_cdc_acm_bulk_in
};
struct usbd_interface intf0;
struct usbd_interface intf1;
struct usbd_interface intf2;
void cdc_acm_msc_init(void)
{
const uint8_t data[10] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30 };
memcpy(&write_buffer[0], data, 10);
memset(&write_buffer[10], 'a', 2038);
usbd_desc_register(cdc_msc_descriptor);
usbd_add_interface(usbd_cdc_acm_init_intf(&intf0));
usbd_add_interface(usbd_cdc_acm_init_intf(&intf1));
usbd_add_endpoint(&cdc_out_ep);
usbd_add_endpoint(&cdc_in_ep);
usbd_add_interface(usbd_msc_init_intf(&intf2, MSC_OUT_EP, MSC_IN_EP));
usbd_initialize();
}
volatile uint8_t dtr_enable = 0;
void usbd_cdc_acm_set_dtr(uint8_t intf, bool dtr)
{
if (dtr) {
dtr_enable = 1;
} else {
dtr_enable = 0;
}
}
void cdc_acm_data_send_with_dtr_test(void)
{
if (dtr_enable) {
ep_tx_busy_flag = true;
usbd_ep_start_write(CDC_IN_EP, write_buffer, 2048);
while (ep_tx_busy_flag) {
}
}
}
#define BLOCK_SIZE 512
#define BLOCK_COUNT 10
typedef struct
{
uint8_t BlockSpace[BLOCK_SIZE];
} BLOCK_TYPE;
BLOCK_TYPE mass_block[BLOCK_COUNT];
void usbd_msc_get_cap(uint8_t lun, uint32_t *block_num, uint16_t *block_size)
{
*block_num = 1000; //Pretend having so many buffer,not has actually.
*block_size = BLOCK_SIZE;
}
int usbd_msc_sector_read(uint32_t sector, uint8_t *buffer, uint32_t length)
{
if (sector < 10)
memcpy(buffer, mass_block[sector].BlockSpace, length);
return 0;
}
int usbd_msc_sector_write(uint32_t sector, uint8_t *buffer, uint32_t length)
{
if (sector < 10)
memcpy(mass_block[sector].BlockSpace, buffer, length);
return 0;
}

View File

@ -0,0 +1,11 @@
[cfg]
# 0: no erase, 1:programmed section erase, 2: chip erase
erase = 1
# skip mode set first para is skip addr, second para is skip len, multi-segment region with ; separated
skip_mode = 0x0, 0x0
# 0: not use isp mode, #1: isp mode
boot2_isp_mode = 0
[FW]
filedir = ./build/build_out/usbd*_$(CHIPNAME).bin
address = 0x000000

View File

@ -0,0 +1,17 @@
#include "usbd_core.h"
#include "bflb_mtimer.h"
#include "board.h"
extern void cdc_acm_msc_init(void);
extern void cdc_acm_data_send_with_dtr_test(void);
int main(void)
{
board_init();
cdc_acm_msc_init();
while (1) {
cdc_acm_data_send_with_dtr_test();
bflb_mtimer_delay_ms(500);
}
}

View File

@ -0,0 +1,7 @@
set(CONFIG_CHERRYUSB 1)
set(CONFIG_CHERRYUSB_DEVICE 1)
set(CONFIG_CHERRYUSB_DEVICE_CDC 1)
set(CONFIG_CHERRYUSB_DEVICE_HID 1)
set(CONFIG_CHERRYUSB_DEVICE_MSC 1)
set(CONFIG_CHERRYUSB_DEVICE_AUDIO 1)
set(CONFIG_CHERRYUSB_DEVICE_VIDEO 1)

View File

@ -0,0 +1,160 @@
/*
* Copyright (c) 2022, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef CHERRYUSB_CONFIG_H
#define CHERRYUSB_CONFIG_H
#define CHERRYUSB_VERSION 0x001000
/* ================ USB common Configuration ================ */
#define CONFIG_USB_PRINTF(...) printf(__VA_ARGS__)
#define usb_malloc(size) malloc(size)
#define usb_free(ptr) free(ptr)
#ifndef CONFIG_USB_DBG_LEVEL
#define CONFIG_USB_DBG_LEVEL USB_DBG_INFO
#endif
/* Enable print with color */
#define CONFIG_USB_PRINTF_COLOR_ENABLE
/* data align size when use dma */
#ifndef CONFIG_USB_ALIGN_SIZE
#define CONFIG_USB_ALIGN_SIZE 4
#endif
/* attribute data into no cache ram */
#define USB_NOCACHE_RAM_SECTION __attribute__((section(".noncacheable")))
/* ================= USB Device Stack Configuration ================ */
/* Ep0 max transfer buffer, specially for receiving data from ep0 out */
#define CONFIG_USBDEV_REQUEST_BUFFER_LEN 256
/* Setup packet log for debug */
// #define CONFIG_USBDEV_SETUP_LOG_PRINT
/* Check if the input descriptor is correct */
// #define CONFIG_USBDEV_DESC_CHECK
/* Enable test mode */
// #define CONFIG_USBDEV_TEST_MODE
//#define CONFIG_USBDEV_TX_THREAD
//#define CONFIG_USBDEV_RX_THREAD
#ifdef CONFIG_USBDEV_TX_THREAD
#ifndef CONFIG_USBDEV_TX_PRIO
#define CONFIG_USBDEV_TX_PRIO 4
#endif
#ifndef CONFIG_USBDEV_TX_STACKSIZE
#define CONFIG_USBDEV_TX_STACKSIZE 2048
#endif
#endif
#ifdef CONFIG_USBDEV_RX_THREAD
#ifndef CONFIG_USBDEV_RX_PRIO
#define CONFIG_USBDEV_RX_PRIO 4
#endif
#ifndef CONFIG_USBDEV_RX_STACKSIZE
#define CONFIG_USBDEV_RX_STACKSIZE 2048
#endif
#endif
#ifndef CONFIG_USBDEV_MSC_BLOCK_SIZE
#define CONFIG_USBDEV_MSC_BLOCK_SIZE 512
#endif
#ifndef CONFIG_USBDEV_MSC_MANUFACTURER_STRING
#define CONFIG_USBDEV_MSC_MANUFACTURER_STRING ""
#endif
#ifndef CONFIG_USBDEV_MSC_PRODUCT_STRING
#define CONFIG_USBDEV_MSC_PRODUCT_STRING ""
#endif
#ifndef CONFIG_USBDEV_MSC_VERSION_STRING
#define CONFIG_USBDEV_MSC_VERSION_STRING "0.01"
#endif
#ifndef CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE
#define CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE 156
#endif
#ifndef CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE
#define CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE 1536
#endif
#ifndef CONFIG_USBDEV_RNDIS_VENDOR_ID
#define CONFIG_USBDEV_RNDIS_VENDOR_ID 0x0000ffff
#endif
#ifndef CONFIG_USBDEV_RNDIS_VENDOR_DESC
#define CONFIG_USBDEV_RNDIS_VENDOR_DESC "CherryUSB"
#endif
#define CONFIG_USBDEV_RNDIS_USING_LWIP
/* ================ USB HOST Stack Configuration ================== */
#define CONFIG_USBHOST_MAX_RHPORTS 1
#define CONFIG_USBHOST_MAX_EXTHUBS 0
#define CONFIG_USBHOST_MAX_EHPORTS 4
#define CONFIG_USBHOST_MAX_INTERFACES 4
#define CONFIG_USBHOST_MAX_INTF_ALTSETTINGS 8
#define CONFIG_USBHOST_MAX_ENDPOINTS 4
#define CONFIG_USBHOST_MAX_CDC_ACM_CLASS 4
#define CONFIG_USBHOST_MAX_HID_CLASS 4
#define CONFIG_USBHOST_MAX_MSC_CLASS 2
#define CONFIG_USBHOST_MAX_AUDIO_CLASS 1
#define CONFIG_USBHOST_MAX_VIDEO_CLASS 1
#define CONFIG_USBHOST_MAX_RNDIS_CLASS 1
#define CONFIG_USBHOST_DEV_NAMELEN 16
#ifndef CONFIG_USBHOST_PSC_PRIO
#define CONFIG_USBHOST_PSC_PRIO 28
#endif
#ifndef CONFIG_USBHOST_PSC_STACKSIZE
#define CONFIG_USBHOST_PSC_STACKSIZE 2048
#endif
//#define CONFIG_USBHOST_GET_STRING_DESC
/* Ep0 max transfer buffer */
#define CONFIG_USBHOST_REQUEST_BUFFER_LEN 512
#ifndef CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT
#define CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT 1000
#endif
#ifndef CONFIG_USBHOST_MSC_TIMEOUT
#define CONFIG_USBHOST_MSC_TIMEOUT 5000
#endif
/* ================ USB Device Port Configuration ================*/
//#define USBD_IRQHandler USBD_IRQHandler
//#define USB_BASE (0x40080000UL)
//#define USB_NUM_BIDIR_ENDPOINTS 4
/* ================ USB Host Port Configuration ==================*/
#define CONFIG_USBHOST_PIPE_NUM 10
/* ================ EHCI Configuration ================ */
#define CONFIG_USB_EHCI_HCCR_BASE (0x20072000)
#define CONFIG_USB_EHCI_HCOR_BASE (0x20072000 + 0x10)
#define CONFIG_USB_EHCI_FRAME_LIST_SIZE 1024
// #define CONFIG_USB_EHCI_INFO_ENABLE
#define CONFIG_USB_EHCI_HCOR_RESERVED_DISABLE
// #define CONFIG_USB_EHCI_CONFIGFLAG
// #define CONFIG_USB_EHCI_PORT_POWER
#endif