- add ch34x_set_data_format()

- add ch34x_set_line_coding()
This commit is contained in:
hathach 2024-01-19 15:58:05 +07:00
parent 23c2d929a1
commit 98781bb903
No known key found for this signature in database
GPG Key ID: F5D50C6D51D17CBA
3 changed files with 107 additions and 74 deletions

View File

@ -27,20 +27,11 @@
#include "tusb.h" #include "tusb.h"
#include "bsp/board_api.h" #include "bsp/board_api.h"
//--------------------------------------------------------------------+ size_t get_console_inputs(uint8_t* buf, size_t bufsize) {
// MACRO TYPEDEF CONSTANT ENUM DECLARATION
//--------------------------------------------------------------------+
//------------- IMPLEMENTATION -------------//
size_t get_console_inputs(uint8_t* buf, size_t bufsize)
{
size_t count = 0; size_t count = 0;
while (count < bufsize) while (count < bufsize) {
{
int ch = board_getchar(); int ch = board_getchar();
if ( ch <= 0 ) break; if (ch <= 0) break;
buf[count] = (uint8_t) ch; buf[count] = (uint8_t) ch;
count++; count++;
@ -49,22 +40,18 @@ size_t get_console_inputs(uint8_t* buf, size_t bufsize)
return count; return count;
} }
void cdc_app_task(void) void cdc_app_task(void) {
{ uint8_t buf[64 + 1]; // +1 for extra null character
uint8_t buf[64+1]; // +1 for extra null character uint32_t const bufsize = sizeof(buf) - 1;
uint32_t const bufsize = sizeof(buf)-1;
uint32_t count = get_console_inputs(buf, bufsize); uint32_t count = get_console_inputs(buf, bufsize);
buf[count] = 0; buf[count] = 0;
// loop over all mounted interfaces // loop over all mounted interfaces
for(uint8_t idx=0; idx<CFG_TUH_CDC; idx++) for (uint8_t idx = 0; idx < CFG_TUH_CDC; idx++) {
{ if (tuh_cdc_mounted(idx)) {
if ( tuh_cdc_mounted(idx) )
{
// console --> cdc interfaces // console --> cdc interfaces
if (count) if (count) {
{
tuh_cdc_write(idx, buf, count); tuh_cdc_write(idx, buf, count);
tuh_cdc_write_flush(idx); tuh_cdc_write_flush(idx);
} }
@ -72,11 +59,14 @@ void cdc_app_task(void)
} }
} }
//--------------------------------------------------------------------+
// TinyUSB callbacks
//--------------------------------------------------------------------+
// Invoked when received new data // Invoked when received new data
void tuh_cdc_rx_cb(uint8_t idx) void tuh_cdc_rx_cb(uint8_t idx) {
{ uint8_t buf[64 + 1]; // +1 for extra null character
uint8_t buf[64+1]; // +1 for extra null character uint32_t const bufsize = sizeof(buf) - 1;
uint32_t const bufsize = sizeof(buf)-1;
// forward cdc interfaces -> console // forward cdc interfaces -> console
uint32_t count = tuh_cdc_read(idx, buf, bufsize); uint32_t count = tuh_cdc_read(idx, buf, bufsize);
@ -85,29 +75,31 @@ void tuh_cdc_rx_cb(uint8_t idx)
printf((char*) buf); printf((char*) buf);
} }
void tuh_cdc_mount_cb(uint8_t idx) // Invoked when a device with CDC interface is mounted
{ // idx is index of cdc interface in the internal pool.
tuh_itf_info_t itf_info = { 0 }; void tuh_cdc_mount_cb(uint8_t idx) {
tuh_itf_info_t itf_info = {0};
tuh_cdc_itf_get_info(idx, &itf_info); tuh_cdc_itf_get_info(idx, &itf_info);
printf("CDC Interface is mounted: address = %u, itf_num = %u\r\n", itf_info.daddr, itf_info.desc.bInterfaceNumber); printf("CDC Interface is mounted: address = %u, itf_num = %u\r\n", itf_info.daddr,
itf_info.desc.bInterfaceNumber);
#ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM
// CFG_TUH_CDC_LINE_CODING_ON_ENUM must be defined for line coding is set by tinyusb in enumeration // CFG_TUH_CDC_LINE_CODING_ON_ENUM must be defined for line coding is set by tinyusb in enumeration
// otherwise you need to call tuh_cdc_set_line_coding() first // otherwise you need to call tuh_cdc_set_line_coding() first
cdc_line_coding_t line_coding = { 0 }; cdc_line_coding_t line_coding = {0};
if ( tuh_cdc_get_local_line_coding(idx, &line_coding) ) if (tuh_cdc_get_local_line_coding(idx, &line_coding)) {
{
printf(" Baudrate: %lu, Stop Bits : %u\r\n", line_coding.bit_rate, line_coding.stop_bits); printf(" Baudrate: %lu, Stop Bits : %u\r\n", line_coding.bit_rate, line_coding.stop_bits);
printf(" Parity : %u, Data Width: %u\r\n", line_coding.parity , line_coding.data_bits); printf(" Parity : %u, Data Width: %u\r\n", line_coding.parity, line_coding.data_bits);
} }
#endif #endif
} }
void tuh_cdc_umount_cb(uint8_t idx) // Invoked when a device with CDC interface is unmounted
{ void tuh_cdc_umount_cb(uint8_t idx) {
tuh_itf_info_t itf_info = { 0 }; tuh_itf_info_t itf_info = {0};
tuh_cdc_itf_get_info(idx, &itf_info); tuh_cdc_itf_get_info(idx, &itf_info);
printf("CDC Interface is unmounted: address = %u, itf_num = %u\r\n", itf_info.daddr, itf_info.desc.bInterfaceNumber); printf("CDC Interface is unmounted: address = %u, itf_num = %u\r\n", itf_info.daddr,
itf_info.desc.bInterfaceNumber);
} }

View File

@ -1327,48 +1327,88 @@ static void ch34x_control_complete(tuh_xfer_t* xfer) {
process_internal_control_complete(p_cdc, xfer); process_internal_control_complete(p_cdc, xfer);
} }
//static bool ch34x_set_data_format(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, static bool ch34x_set_data_format(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits,
// tuh_xfer_cb_t complete_cb, uintptr_t user_data) { tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
// uint8_t const lcr = ch34x_get_lcr(stop_bits, parity, data_bits); p_cdc->requested_line_coding.stop_bits = stop_bits;
// p_cdc->requested_line_coding.stop_bits = stop_bits; p_cdc->requested_line_coding.parity = parity;
// p_cdc->requested_line_coding.parity = parity; p_cdc->requested_line_coding.data_bits = data_bits;
// p_cdc->requested_line_coding.data_bits = data_bits;
//
// TU_ASSERT (ch34x_control_out(p_cdc, CH34X_REQ_WRITE_REG, CH32X_REG16_LCR2_LCR, lcr,
// complete_cb ? ch34x_control_complete : NULL, user_data));
// return false;
//}
static bool ch34x_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate,
tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
uint16_t const div_ps = ch34x_get_divisor_prescaler(baudrate);
TU_VERIFY(div_ps != 0);
p_cdc->requested_line_coding.bit_rate = baudrate;
p_cdc->user_control_cb = complete_cb;
TU_ASSERT(ch34x_write_reg(p_cdc, CH34X_REG16_DIVISOR_PRESCALER, div_ps,
complete_cb ? ch34x_control_complete : NULL, user_data));
uint8_t const lcr = ch34x_get_lcr(stop_bits, parity, data_bits);
TU_ASSERT (ch34x_control_out(p_cdc, CH34X_REQ_WRITE_REG, CH32X_REG16_LCR2_LCR, lcr,
complete_cb ? ch34x_control_complete : NULL, user_data));
return true; return true;
} }
//static void ch34x_set_line_coding_stage1(tuh_xfer_t* xfer) { static bool ch34x_write_reg_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate,
// tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
//} uint16_t const div_ps = ch34x_get_divisor_prescaler(baudrate);
TU_VERIFY(div_ps != 0);
TU_ASSERT(ch34x_write_reg(p_cdc, CH34X_REG16_DIVISOR_PRESCALER, div_ps,
complete_cb, user_data));
return true;
}
static bool ch34x_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate,
tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
p_cdc->requested_line_coding.bit_rate = baudrate;
p_cdc->user_control_cb = complete_cb;
TU_ASSERT(ch34x_write_reg_baudrate(p_cdc, baudrate,
complete_cb ? ch34x_control_complete : NULL, user_data));
return true;
}
static void ch34x_set_line_coding_stage1_complete(tuh_xfer_t* xfer) {
uint8_t const itf_num = 0;
uint8_t const idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num);
cdch_interface_t* p_cdc = get_itf(idx);
TU_ASSERT(p_cdc, );
if (xfer->result == XFER_RESULT_SUCCESS) {
// stage 1 success, continue to stage 2
p_cdc->line_coding.bit_rate = p_cdc->requested_line_coding.bit_rate;
TU_ASSERT(ch34x_set_data_format(p_cdc, p_cdc->requested_line_coding.stop_bits, p_cdc->requested_line_coding.parity,
p_cdc->requested_line_coding.data_bits, ch34x_control_complete, xfer->user_data), );
} else {
// stage 1 failed, notify user
xfer->complete_cb = p_cdc->user_control_cb;
if (xfer->complete_cb) {
xfer->complete_cb(xfer);
}
}
}
// 2 stages: set baudrate (stage1) + set data format (stage2)
static bool ch34x_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, static bool ch34x_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding,
tuh_xfer_cb_t complete_cb, uintptr_t user_data) { tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
// p_cdc->baudrate_requested = line_coding->bit_rate; p_cdc->requested_line_coding = *line_coding;
// p_cdc->user_control_cb = complete_cb; p_cdc->user_control_cb = complete_cb;
// uint8_t factor, divisor, lcr;
// TU_ASSERT (ch34x_get_factor_divisor(line_coding->bit_rate, &factor, &divisor)); if (complete_cb) {
// TU_ASSERT (ch34x_get_lcr(line_coding, &lcr)); // stage 1 set baudrate
// TU_ASSERT (ch34x_control_out(p_cdc, CH34X_REQ_SERIAL_INIT, (uint16_t) (lcr << 8 | 0x9c), (uint16_t) (factor << 8 | 0x80 | divisor), TU_ASSERT(ch34x_write_reg_baudrate(p_cdc, line_coding->bit_rate,
// complete_cb ? ch34x_control_complete : NULL, user_data)); ch34x_set_line_coding_stage1_complete, user_data));
(void) p_cdc; } else {
(void) line_coding; // sync call
(void) complete_cb; xfer_result_t result;
(void) user_data;
// stage 1 set baudrate
TU_ASSERT(ch34x_write_reg_baudrate(p_cdc, line_coding->bit_rate, NULL, (uintptr_t) &result));
TU_VERIFY(result == XFER_RESULT_SUCCESS);
p_cdc->line_coding.bit_rate = line_coding->bit_rate;
// stage 2 set data format
TU_ASSERT(ch34x_set_data_format(p_cdc, line_coding->stop_bits, line_coding->parity, line_coding->data_bits,
NULL, (uintptr_t) &result));
TU_VERIFY(result == XFER_RESULT_SUCCESS);
p_cdc->line_coding.stop_bits = line_coding->stop_bits;
p_cdc->line_coding.parity = line_coding->parity;
p_cdc->line_coding.data_bits = line_coding->data_bits;
// update transfer result, user_data is expected to point to xfer_result_t
if (user_data) {
user_data = result;
}
}
return true; return true;
} }

View File

@ -63,7 +63,8 @@
#define CH341_REG_0x2C 0x2C // undocumented register #define CH341_REG_0x2C 0x2C // undocumented register
#define CH341_REG_0x27 0x27 // hardware flow control (cts/rts) #define CH341_REG_0x27 0x27 // hardware flow control (cts/rts)
#define CH34X_REG16_DIVISOR_PRESCALER TU_U16(CH34X_REG_DIVISOR, CH34X_REG_PRESCALER) #define CH34X_REG16_DIVISOR_PRESCALER TU_U16(CH34X_REG_DIVISOR, CH34X_REG_PRESCALER)
#define CH32X_REG16_LCR2_LCR TU_U16(CH34X_REG_LCR2, CH34X_REG_LCR)
// modem control bits // modem control bits
#define CH34X_BIT_RTS ( 1 << 6 ) #define CH34X_BIT_RTS ( 1 << 6 )