From e0d41ca05686e2e1dc5a3e4a366494bf30bbe075 Mon Sep 17 00:00:00 2001 From: cnlohr Date: Mon, 8 Jul 2024 23:52:42 -0700 Subject: [PATCH] Fix a multitude of bugs. Some sillier than others. --- ch32v/ch32v003fun | 2 +- ch32v/ch32v203-goertzel/README.md | 29 +++++ ch32v/ch32v203-goertzel/adcgoertzel.c | 73 ++++++++---- ch32v/ch32v203-goertzel/usb_config.h | 157 ++++++++++++++++++++++++++ 4 files changed, 238 insertions(+), 23 deletions(-) create mode 100644 ch32v/ch32v203-goertzel/README.md create mode 100644 ch32v/ch32v203-goertzel/usb_config.h diff --git a/ch32v/ch32v003fun b/ch32v/ch32v003fun index aa91922..7bf80c9 160000 --- a/ch32v/ch32v003fun +++ b/ch32v/ch32v003fun @@ -1 +1 @@ -Subproject commit aa91922a0690ab5c8f069a628d5a1c9aa3bcacbe +Subproject commit 7bf80c92ccc38aa4b25871739618309e141e77f1 diff --git a/ch32v/ch32v203-goertzel/README.md b/ch32v/ch32v203-goertzel/README.md new file mode 100644 index 0000000..0513839 --- /dev/null +++ b/ch32v/ch32v203-goertzel/README.md @@ -0,0 +1,29 @@ +# How to use this + + * Display on PB8/PB9 for SCL/SDA + * Analog is on PA7 + +First, use FFT, then look in the middle for the highest bin @. This is the # of pixels from the left side of the screen you are. + +Then edit ttest.c, + +``` + g_goertzel_omega_per_sample = (47.0/256) * 3.1415926535*2.0*65536; +``` + +where 47.0 in this case is the bin # from the FFT. + +Change this, `make test` + +Then copy the values: +const int32_t g_goertzel_omega_per_sample = 75599; +const int32_t g_goertzel_coefficient = 870257651; +const int32_t g_goertzel_coefficient_s = 1963246708; + +into the top of adcgoertzel.c + + +TODO: TODO: Test HTML values. + +TODO: TODO: g_goertzel_omega_per_sample lokos WRONG. + diff --git a/ch32v/ch32v203-goertzel/adcgoertzel.c b/ch32v/ch32v203-goertzel/adcgoertzel.c index 440ddc0..c28db87 100644 --- a/ch32v/ch32v203-goertzel/adcgoertzel.c +++ b/ch32v/ch32v203-goertzel/adcgoertzel.c @@ -60,19 +60,22 @@ SOFTWARE. #include "ch32v003fun.h" #include +#include #include #define SH1107_128x128 #define SSD1306_REMAP_I2C #define PWM_OUTPUT #define ENABLE_OLED +#define PROFILING_PIN PA0 + #include "ssd1306_i2c.h" #include "ssd1306.h" #include "./usb_config.h" #include "../ch32v003fun/examples_v20x/otg_device/otgusb.h" -#define ADC_BUFFSIZE 1024 +#define ADC_BUFFSIZE 512 volatile uint16_t adc_buffer[ADC_BUFFSIZE]; @@ -135,7 +138,7 @@ const int32_t g_goertzel_coefficient_s = 2129111628; #endif -int intensity_max = 1; +int intensity_average = 1; #define LOG_GOERTZEL_LIST 512 int16_t qibaselogs[LOG_GOERTZEL_LIST*2]; @@ -262,7 +265,6 @@ uint32_t tc; volatile uint16_t * adc_tail = adc_buffer; - uint32_t g_goertzel_samples; uint32_t g_goertzel_outs; int32_t g_goertzel, g_goertzelp, g_goertzelp2; @@ -271,7 +273,9 @@ int32_t g_goertzelp_store, g_goertzelp2_store; void DMA1_Channel1_IRQHandler( void ) __attribute__((interrupt)); void DMA1_Channel1_IRQHandler( void ) { - //GPIOD->BSHR = 1; // Turn on GPIOD0 for profiling +#ifdef PROFILING_PIN + funDigitalWrite( PROFILING_PIN, 1 ); +#endif // Timer goes backwards when we are moving forwards. volatile uint16_t * adc_buffer_end = 0; @@ -285,6 +289,7 @@ void DMA1_Channel1_IRQHandler( void ) uint32_t goertzel_samples = g_goertzel_samples; // Backup flags. volatile int intfr = DMA1->INTFR; + do { // Clear all possible flags. @@ -381,17 +386,18 @@ void DMA1_Channel1_IRQHandler( void ) int s = rr * rr + ri * ri; //int intensity = 1<<( ( 32 - __builtin_clz(s) )/2); - - int intensity = (abs(rr) + abs(ri)) * 26100 / 32768; + #define ABS(x) (((x)<0)?-(x):(x)) + int intensity = (ABS(rr) + ABS(ri)) * 26100 / 32768; // Found experimentally (Also try to avoid divide-by-zero. + if( intensity == 0 ) + intensity = 1; intensity = (intensity + s/intensity)/2; intensity = (intensity + s/intensity)/2; intensity = (intensity + s/intensity)/2; - - intensity_max = intensity_max - (intensity_max>>10) + (intensity>>2); + intensity_average = intensity_average - (intensity_average>>10) + (intensity); #ifdef PWM_OUTPUT - intensity = intensity * g_volume_pwm * g_pwm_period / (intensity_max>>(7-7)); + intensity = intensity * g_volume_pwm * g_pwm_period / (intensity_average>>(10-8)); if( intensity >= g_pwm_period-1 ) intensity = g_pwm_period-2; if( intensity < 1 ) intensity = 1; TIM1->CH2CVR = intensity; // Actual duty cycle (Off to begin with) @@ -404,7 +410,6 @@ void DMA1_Channel1_IRQHandler( void ) } } - intfr = DMA1->INTFR; } while( intfr & DMA1_IT_GL1 ); @@ -412,8 +417,10 @@ void DMA1_Channel1_IRQHandler( void ) g_goertzelp = goertzelp; g_goertzel = goertzel; g_goertzel_samples = goertzel_samples; - - //GPIOD->BSHR = 1<<16; // Turn off GPIOD0 for profiling + +#ifdef PROFILING_PIN + funDigitalWrite( PROFILING_PIN, 0 ); // For profiling +#endif } static inline uint32_t gets2() @@ -453,8 +460,8 @@ void InnerLoop() int rr = qibaselogs[glread++]; int ri = qibaselogs[glread++]; - rr = rr * 100 / (intensity_max>>4); - ri = ri * 100 / (intensity_max>>4); + rr = rr * 512 / (intensity_average>>4); + ri = ri * 512 / (intensity_average>>4); rr += 64; ri += 64; @@ -471,7 +478,7 @@ void InnerLoop() #ifdef ENABLE_OLED char cts[32]; - snprintf( cts, 32, "%d %d", intensity_max, intensity ); + snprintf( cts, 32, "%d", intensity_average ); ssd1306_drawstr( 0, 0, cts, 1 ); @@ -481,6 +488,7 @@ void InnerLoop() //if( ik == sizeof(ssd1306_buffer) ) ik = 0; ssd1306_setbuf(0); + #else Delay_Ms(17); #endif @@ -537,8 +545,14 @@ int main() #ifdef ENABLE_OLED ssd1306_i2c_setup(); ssd1306_i2c_init(); - ssd1306_init(); - ssd1306_setbuf(0); + + if( ssd1306_init() ) + printf( "Failed to initialize OLED\n" ); + else + printf( "Initialized OLED\n" ); + + ssd1306_setbuf(1); + ssd1306_refresh(); #endif #if 0 @@ -569,12 +583,15 @@ int main() EXTEN->EXTEN_CTR |= EXTEN_OPA_NSEL; #endif +#ifdef PROFILING_PIN + funPinMode( PROFILING_PIN, GPIO_CFGLR_OUT_50Mhz_PP ); +#endif + SetupTimer1(); - - funPinMode( PA0, GPIO_CFGLR_OUT_10Mhz_PP ); - USBOTGSetup(); + + InnerLoop(); } @@ -583,18 +600,25 @@ int main() uint8_t scratchpad[256]; - +int g_isConfigurePacket = 0; int HandleHidUserSetReportSetup( struct _USBState * ctx, tusb_control_request_t * req ) { int id = req->wValue & 0xff; - if( id == 0xaa ) + g_isConfigurePacket = 0; + if( id == 0xaa && req->wLength < sizeof( scratchpad ) ) { // memset( scratchpad, 0x55, sizeof(scratchpad) ); //printf( "SET REPORT! %d [%02x]\n", req->wLength, scratchpad[200] ); ctx->pCtrlPayloadPtr = scratchpad; return req->wLength; } + else if( id == 0xac && req->wLength < sizeof( scratchpad ) ) + { + g_isConfigurePacket = 1; + ctx->pCtrlPayloadPtr = scratchpad; + return req->wLength; + } return 0; } @@ -623,6 +647,11 @@ int HandleHidUserReportDataIn( struct _USBState * ctx, uint8_t * data, int len ) void HandleHidUserReportOutComplete( struct _USBState * ctx ) { + if( g_isConfigurePacket ) + { + printf( "Is Configure Packet\n" ); + g_isConfigurePacket = 0; + } return; } diff --git a/ch32v/ch32v203-goertzel/usb_config.h b/ch32v/ch32v203-goertzel/usb_config.h new file mode 100644 index 0000000..d28e0e4 --- /dev/null +++ b/ch32v/ch32v203-goertzel/usb_config.h @@ -0,0 +1,157 @@ +#ifndef _USB_CONFIG_H +#define _USB_CONFIG_H + +#include "funconfig.h" +#include "ch32v003fun.h" + +#define FUSB_CONFIG_EPS 2 // Include EP0 in this count +#define FUSB_SUPPORTS_SLEEP 0 +#define FUSB_HID_INTERFACES 1 +#define FUSB_CURSED_TURBO_DMA 0 // Hacky, but seems fine, shaves 2.5us off filling 64-byte buffers. +#define FUSB_HID_USER_REPORTS 1 +#define FUSB_IO_PROFILE 1 +#define FUSB_USE_HPE FUNCONF_ENABLE_HPE + +#include "usb_defines.h" + +//Taken from http://www.usbmadesimple.co.uk/ums_ms_desc_dev.htm +static const uint8_t device_descriptor[] = { + 18, //Length + 1, //Type (Device) + 0x00, 0x02, //Spec + 0x0, //Device Class + 0x0, //Device Subclass + 0x0, //Device Protocol (000 = use config descriptor) + 64, //Max packet size for EP0 (This has to be 8 because of the USB Low-Speed Standard) + 0x09, 0x12, //ID Vendor + 0x35, 0xd0, //ID Product + 0x03, 0x00, //ID Rev + 1, //Manufacturer string + 2, //Product string + 3, //Serial string + 1, //Max number of configurations +}; + +static const uint8_t HIDAPIRepDesc[ ] = +{ + HID_USAGE_PAGE ( 0xff ), // Vendor-defined page. + HID_USAGE ( 0x00 ), + HID_REPORT_SIZE ( 8 ), + HID_COLLECTION ( HID_COLLECTION_LOGICAL ), + HID_REPORT_COUNT ( 254 ), + HID_REPORT_ID ( 0xaa ) + HID_USAGE ( 0x01 ), + HID_FEATURE ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) , + HID_REPORT_COUNT ( 63 ), // For use with `hidapitester --vidpid 1209/D003 --open --read-feature 171` + HID_REPORT_ID ( 0xab ) + HID_USAGE ( 0x01 ), + HID_FEATURE ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) , + HID_REPORT_COUNT ( 63 ), // For configuring the setup. + HID_REPORT_ID ( 0xac ) + HID_USAGE ( 0x01 ), + HID_FEATURE ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) , + HID_REPORT_COUNT ( 254 ), // For receiving IQ data on host. + HID_REPORT_ID ( 0xad ) + HID_USAGE ( 0x01 ), + HID_FEATURE ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) , + HID_COLLECTION_END, +}; + +/* Configuration Descriptor Set */ +static const uint8_t config_descriptor[ ] = +{ + /* Configuration Descriptor */ + 0x09, // bLength + 0x02, // bDescriptorType + 0x22, 0x00, // wTotalLength + 0x01, // bNumInterfaces (3) + 0x01, // bConfigurationValue + 0x00, // iConfiguration + 0xA0, // bmAttributes: Bus Powered; Remote Wakeup + 0x32, // MaxPower: 100mA + + /* Interface Descriptor (Special) */ + 0x09, // bLength + 0x04, // bDescriptorType + 0x00, // bInterfaceNumber + 0x01, // bAlternateSetting + 0x01, // bNumEndpoints + 0x03, // bInterfaceClass + 0x00, // bInterfaceSubClass + 0xff, // bInterfaceProtocol: OTher + 0x00, // iInterface + + /* HID Descriptor (Special) */ + 0x09, // bLength + 0x21, // bDescriptorType + 0x10, 0x01, // bcdHID + 0x00, // bCountryCode + 0x01, // bNumDescriptors + 0x22, // bDescriptorType + sizeof(HIDAPIRepDesc), 0x00, // wDescriptorLength + + /* Endpoint Descriptor (Special) */ + 0x07, // bLength + 0x05, // bDescriptorType + 0x81, // bEndpointAddress: IN Endpoint 1 + 0x03, // bmAttributes + 0x08, 0x00, // wMaxPacketSize + 0xff, // bInterval: slow. +}; + + + +#define STR_MANUFACTURER u"CNLohr" +#define STR_PRODUCT u"lolra ch32v203 goertzel test" +#define STR_SERIAL u"CUSTOMDEVICE000" + +struct usb_string_descriptor_struct { + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t wString[]; +}; +const static struct usb_string_descriptor_struct string0 __attribute__((section(".rodata"))) = { + 4, + 3, + {0x0409} +}; +const static struct usb_string_descriptor_struct string1 __attribute__((section(".rodata"))) = { + sizeof(STR_MANUFACTURER), + 3, + STR_MANUFACTURER +}; +const static struct usb_string_descriptor_struct string2 __attribute__((section(".rodata"))) = { + sizeof(STR_PRODUCT), + 3, + STR_PRODUCT +}; +const static struct usb_string_descriptor_struct string3 __attribute__((section(".rodata"))) = { + sizeof(STR_SERIAL), + 3, + STR_SERIAL +}; + +// This table defines which descriptor data is sent for each specific +// request from the host (in wValue and wIndex). +const static struct descriptor_list_struct { + uint32_t lIndexValue; + const uint8_t *addr; + uint8_t length; +} descriptor_list[] = { + {0x00000100, device_descriptor, sizeof(device_descriptor)}, + {0x00000200, config_descriptor, sizeof(config_descriptor)}, + // interface number // 2200 for hid descriptors. + {0x00002200, HIDAPIRepDesc, sizeof(HIDAPIRepDesc)}, + + {0x00002100, config_descriptor + 18, 9 }, // Not sure why, this seems to be useful for Windows + Android. + + {0x00000300, (const uint8_t *)&string0, 4}, + {0x04090301, (const uint8_t *)&string1, sizeof(STR_MANUFACTURER)}, + {0x04090302, (const uint8_t *)&string2, sizeof(STR_PRODUCT)}, + {0x04090303, (const uint8_t *)&string3, sizeof(STR_SERIAL)} +}; +#define DESCRIPTOR_LIST_ENTRIES ((sizeof(descriptor_list))/(sizeof(struct descriptor_list_struct)) ) + + +#endif +