diff options
Diffstat (limited to 'platforms/chibios/drivers')
-rw-r--r-- | platforms/chibios/drivers/analog.c | 111 | ||||
-rw-r--r-- | platforms/chibios/drivers/audio_dac.h | 34 | ||||
-rw-r--r-- | platforms/chibios/drivers/audio_dac_additive.c | 48 | ||||
-rw-r--r-- | platforms/chibios/drivers/audio_pwm_hardware.c | 8 |
4 files changed, 169 insertions, 32 deletions
diff --git a/platforms/chibios/drivers/analog.c b/platforms/chibios/drivers/analog.c index bf84ce8f76..fb146df936 100644 --- a/platforms/chibios/drivers/analog.c +++ b/platforms/chibios/drivers/analog.c @@ -31,7 +31,15 @@ #endif #if STM32_ADCV3_OVERSAMPLING -# error "STM32 ADCV3 Oversampling is not supported at this time." +// Apparently all ADCV3 chips that support oversampling (STM32L4xx, STM32L4xx+, +// STM32G4xx, STM32WB[35]x) have errata like “Wrong ADC result if conversion +// done late after calibration or previous conversion”; the workaround is to +// perform a dummy conversion and discard its result. STM32G4xx chips also +// have the “ADC channel 0 converted instead of the required ADC channel” +// errata, one workaround for which is also to perform a dummy conversion. +# define ADC_DUMMY_CONVERSIONS_AT_START 1 +#else +# define ADC_DUMMY_CONVERSIONS_AT_START 0 #endif // Otherwise assume V3 @@ -76,8 +84,10 @@ #ifndef ADC_COUNT # if defined(RP2040) || defined(STM32F0XX) || defined(STM32F1XX) || defined(STM32F4XX) || defined(GD32VF103) || defined(WB32F3G71xx) || defined(WB32FQ95xx) # define ADC_COUNT 1 -# elif defined(STM32F3XX) +# elif defined(STM32F3XX) || defined(STM32G4XX) # define ADC_COUNT 4 +# elif defined(STM32L4XX) +# define ADC_COUNT 3 # else # error "ADC_COUNT has not been set for this ARM microcontroller." # endif @@ -89,13 +99,24 @@ # error "The ARM ADC implementation currently only supports reading one channel at a time." #endif +// Add dummy conversions as extra channels (this would work only on chips that +// have multiple channel index fields instead of a channel mask, but all chips +// that need that workaround are like that). +#define ADC_TOTAL_CHANNELS (ADC_DUMMY_CONVERSIONS_AT_START + ADC_NUM_CHANNELS) + #ifndef ADC_BUFFER_DEPTH # define ADC_BUFFER_DEPTH 1 #endif // For more sampling rate options, look at hal_adc_lld.h in ChibiOS -#ifndef ADC_SAMPLING_RATE -# define ADC_SAMPLING_RATE ADC_SMPR_SMP_1P5 +#if !defined(ADC_SAMPLING_RATE) && !defined(RP2040) +# if defined(ADC_SMPR_SMP_1P5) +# define ADC_SAMPLING_RATE ADC_SMPR_SMP_1P5 +# elif defined(ADC_SMPR_SMP_2P5) // STM32L4XX, STM32L4XXP, STM32G4XX, STM32WBXX +# define ADC_SAMPLING_RATE ADC_SMPR_SMP_2P5 +# else +# error "Cannot determine the default ADC_SAMPLING_RATE for this MCU." +# endif #endif // Options are 12, 10, 8, and 6 bit. @@ -108,7 +129,7 @@ #endif static ADCConfig adcCfg = {}; -static adcsample_t sampleBuffer[ADC_NUM_CHANNELS * ADC_BUFFER_DEPTH]; +static adcsample_t sampleBuffer[ADC_TOTAL_CHANNELS * ADC_BUFFER_DEPTH]; // Initialize to max number of ADCs, set to empty object to initialize all to false. static bool adcInitialized[ADC_COUNT] = {}; @@ -116,7 +137,7 @@ static bool adcInitialized[ADC_COUNT] = {}; // TODO: add back TR handling??? static ADCConversionGroup adcConversionGroup = { .circular = FALSE, - .num_channels = (uint16_t)(ADC_NUM_CHANNELS), + .num_channels = (uint16_t)(ADC_TOTAL_CHANNELS), #if defined(USE_ADCV1) .cfgr1 = ADC_CFGR1_CONT | ADC_RESOLUTION, .smpr = ADC_SAMPLING_RATE, @@ -240,6 +261,74 @@ __attribute__((weak)) adc_mux pinToMux(pin_t pin) { case C5: return TO_MUX( ADC_CHANNEL_IN15, 0 ); // STM32F103x[C-G] in 144-pin packages also have analog inputs on F6...F10, but they are on ADC3, and the // ChibiOS ADC driver for STM32F1xx currently supports only ADC1, therefore these pins are not usable. +#elif defined(STM32L4XX) + case A0: return TO_MUX( ADC_CHANNEL_IN5, 0 ); // Can also be ADC2 in some cases + case A1: return TO_MUX( ADC_CHANNEL_IN6, 0 ); // Can also be ADC2 in some cases + case A2: return TO_MUX( ADC_CHANNEL_IN7, 0 ); // Can also be ADC2 + case A3: return TO_MUX( ADC_CHANNEL_IN8, 0 ); // Can also be ADC2 + case A4: return TO_MUX( ADC_CHANNEL_IN9, 0 ); // Can also be ADC2 + case A5: return TO_MUX( ADC_CHANNEL_IN10, 0 ); // Can also be ADC2 + case A6: return TO_MUX( ADC_CHANNEL_IN11, 0 ); // Can also be ADC2 + case A7: return TO_MUX( ADC_CHANNEL_IN12, 0 ); // Can also be ADC2 + case B0: return TO_MUX( ADC_CHANNEL_IN15, 0 ); // Can also be ADC2 + case B1: return TO_MUX( ADC_CHANNEL_IN16, 0 ); // Can also be ADC2 + case C0: return TO_MUX( ADC_CHANNEL_IN1, 0 ); // Can also be ADC2 or ADC3 + case C1: return TO_MUX( ADC_CHANNEL_IN2, 0 ); // Can also be ADC2 or ADC3 + case C2: return TO_MUX( ADC_CHANNEL_IN3, 0 ); // Can also be ADC2 or ADC3 + case C3: return TO_MUX( ADC_CHANNEL_IN4, 0 ); // Can also be ADC2 or ADC3 + case C4: return TO_MUX( ADC_CHANNEL_IN13, 0 ); // Can also be ADC2 + case C5: return TO_MUX( ADC_CHANNEL_IN14, 0 ); // Can also be ADC2 +# if STM32_HAS_GPIOF && STM32_ADC_USE_ADC3 + case F3: return TO_MUX( ADC_CHANNEL_IN6, 2 ); + case F4: return TO_MUX( ADC_CHANNEL_IN7, 2 ); + case F5: return TO_MUX( ADC_CHANNEL_IN8, 2 ); + case F6: return TO_MUX( ADC_CHANNEL_IN9, 2 ); + case F7: return TO_MUX( ADC_CHANNEL_IN10, 2 ); + case F8: return TO_MUX( ADC_CHANNEL_IN11, 2 ); + case F9: return TO_MUX( ADC_CHANNEL_IN12, 2 ); + case F10: return TO_MUX( ADC_CHANNEL_IN13, 2 ); +# endif +#elif defined(STM32G4XX) + case A0: return TO_MUX( ADC_CHANNEL_IN1, 0 ); // Can also be ADC2 + case A1: return TO_MUX( ADC_CHANNEL_IN2, 0 ); // Can also be ADC2 + case A2: return TO_MUX( ADC_CHANNEL_IN3, 0 ); + case A3: return TO_MUX( ADC_CHANNEL_IN4, 0 ); + case A4: return TO_MUX( ADC_CHANNEL_IN17, 1 ); + case A5: return TO_MUX( ADC_CHANNEL_IN13, 1 ); + case A6: return TO_MUX( ADC_CHANNEL_IN3, 1 ); + case A7: return TO_MUX( ADC_CHANNEL_IN4, 1 ); + case B0: return TO_MUX( ADC_CHANNEL_IN15, 0 ); // Can also be ADC3 + case B1: return TO_MUX( ADC_CHANNEL_IN12, 0 ); // Can also be ADC3 + case B2: return TO_MUX( ADC_CHANNEL_IN12, 1 ); + case B11: return TO_MUX( ADC_CHANNEL_IN14, 0 ); // Can also be ADC2 + case B12: return TO_MUX( ADC_CHANNEL_IN11, 0 ); // Can also be ADC4 + case B13: return TO_MUX( ADC_CHANNEL_IN5, 2 ); + case B14: return TO_MUX( ADC_CHANNEL_IN5, 0 ); // Can also be ADC4 + case B15: return TO_MUX( ADC_CHANNEL_IN15, 1 ); // Can also be ADC4 + case C0: return TO_MUX( ADC_CHANNEL_IN6, 0 ); // Can also be ADC2 + case C1: return TO_MUX( ADC_CHANNEL_IN7, 0 ); // Can also be ADC2 + case C2: return TO_MUX( ADC_CHANNEL_IN8, 0 ); // Can also be ADC2 + case C3: return TO_MUX( ADC_CHANNEL_IN9, 0 ); // Can also be ADC2 + case C4: return TO_MUX( ADC_CHANNEL_IN5, 1 ); + case C5: return TO_MUX( ADC_CHANNEL_IN11, 1 ); + case D8: return TO_MUX( ADC_CHANNEL_IN12, 3 ); + case D9: return TO_MUX( ADC_CHANNEL_IN13, 3 ); + case D10: return TO_MUX( ADC_CHANNEL_IN7, 2 ); // Can also be ADC4 + case D11: return TO_MUX( ADC_CHANNEL_IN8, 2 ); // Can also be ADC4 + case D12: return TO_MUX( ADC_CHANNEL_IN9, 2 ); // Can also be ADC4 + case D13: return TO_MUX( ADC_CHANNEL_IN10, 2 ); // Can also be ADC4 + case D14: return TO_MUX( ADC_CHANNEL_IN11, 2 ); // Can also be ADC4 + case E5: return TO_MUX( ADC_CHANNEL_IN2, 3 ); + case E7: return TO_MUX( ADC_CHANNEL_IN4, 2 ); + case E8: return TO_MUX( ADC_CHANNEL_IN6, 2 ); // Can also be ADC4 + case E9: return TO_MUX( ADC_CHANNEL_IN2, 2 ); + case E10: return TO_MUX( ADC_CHANNEL_IN14, 2 ); // Can also be ADC4 + case E11: return TO_MUX( ADC_CHANNEL_IN15, 2 ); // Can also be ADC4 + case E12: return TO_MUX( ADC_CHANNEL_IN16, 2 ); // Can also be ADC4 + case E13: return TO_MUX( ADC_CHANNEL_IN3, 2 ); + case E14: return TO_MUX( ADC_CHANNEL_IN1, 3 ); + case F0: return TO_MUX( ADC_CHANNEL_IN10, 0 ); + case F1: return TO_MUX( ADC_CHANNEL_IN10, 1 ); #elif defined(RP2040) case 26U: return TO_MUX(0, 0); case 27U: return TO_MUX(1, 0); @@ -306,7 +395,11 @@ int16_t adc_read(adc_mux mux) { #elif defined(RP2040) adcConversionGroup.channel_mask = 1 << mux.input; #else - adcConversionGroup.sqr[0] = ADC_SQR1_SQ1_N(mux.input); + adcConversionGroup.sqr[0] = ADC_SQR1_SQ1_N(mux.input) +# if ADC_DUMMY_CONVERSIONS_AT_START >= 1 + | ADC_SQR1_SQ2_N(mux.input) +# endif + ; #endif ADCDriver* targetDriver = intToADCDriver(mux.adc); @@ -321,9 +414,9 @@ int16_t adc_read(adc_mux mux) { #if defined(USE_ADCV2) || defined(RP2040) // fake 12-bit -> N-bit scale - return (*sampleBuffer) >> (12 - ADC_RESOLUTION); + return (sampleBuffer[ADC_DUMMY_CONVERSIONS_AT_START]) >> (12 - ADC_RESOLUTION); #else // already handled as part of adcConvert - return *sampleBuffer; + return sampleBuffer[ADC_DUMMY_CONVERSIONS_AT_START]; #endif } diff --git a/platforms/chibios/drivers/audio_dac.h b/platforms/chibios/drivers/audio_dac.h index 07cd622ead..2f62d12934 100644 --- a/platforms/chibios/drivers/audio_dac.h +++ b/platforms/chibios/drivers/audio_dac.h @@ -24,11 +24,6 @@ #endif /** - * Size of the dac_buffer arrays. All must be the same size. - */ -#define AUDIO_DAC_BUFFER_SIZE 256U - -/** * Highest value allowed sample value. * since the DAC is limited to 12 bit, the absolute max is 0xfff = 4095U; @@ -97,6 +92,35 @@ #endif /** + * Size of the dac_buffer array. This controls the length of the runtime buffer + * which accumulates the data to be sent to the DAC every few milliseconds, and + * it does not need to correspond to the length of the wavetable for the chosen + * waveform defined by AUDIO_DAC_SAMPLE_WAVEFORM_* in the additive DAC driver. + * By default, this is set to be as close to 3.3 ms as possible, giving 300 DAC + * interrupts per second. Any smaller and the interrupt load gets too heavy and + * this results in crackling due to buffer underrun in the additive DAC driver; + * too large and the RAM (additive driver) or flash (basic driver) usage may be + * too high, causing build failures, and matrix scanning is liable to have long + * periodic pauses that delay key presses or releases or fully lose short taps. + * Large buffers also cause notes to take longer to stop after they should from + * music mode or MIDI input. + * This should be a power of 2 for maximum compatibility. + */ +#ifndef AUDIO_DAC_BUFFER_SIZE +# if AUDIO_DAC_SAMPLE_RATE < 5100U +# define AUDIO_DAC_BUFFER_SIZE 16U +# elif AUDIO_DAC_SAMPLE_RATE < 9900U +# define AUDIO_DAC_BUFFER_SIZE 32U +# elif AUDIO_DAC_SAMPLE_RATE < 19500U +# define AUDIO_DAC_BUFFER_SIZE 64U +# elif AUDIO_DAC_SAMPLE_RATE < 38700U +# define AUDIO_DAC_BUFFER_SIZE 128U +# else +# define AUDIO_DAC_BUFFER_SIZE 256U +# endif +#endif + +/** * The number of tones that can be played simultaneously. If too high a value * is used here, the keyboard will freeze and glitch-out when that many tones * are being played. diff --git a/platforms/chibios/drivers/audio_dac_additive.c b/platforms/chibios/drivers/audio_dac_additive.c index 26e044b048..d6fde42b68 100644 --- a/platforms/chibios/drivers/audio_dac_additive.c +++ b/platforms/chibios/drivers/audio_dac_additive.c @@ -53,35 +53,39 @@ #ifdef AUDIO_DAC_SAMPLE_WAVEFORM_SINE /* one full sine wave over [0,2*pi], but shifted up one amplitude and left pi/4; for the samples to start at 0 */ -static const dacsample_t dac_buffer_sine[AUDIO_DAC_BUFFER_SIZE] = { +static const dacsample_t dac_buffer_sine[] = { // 256 values, max 4095 0x0, 0x1, 0x2, 0x6, 0xa, 0xf, 0x16, 0x1e, 0x27, 0x32, 0x3d, 0x4a, 0x58, 0x67, 0x78, 0x89, 0x9c, 0xb0, 0xc5, 0xdb, 0xf2, 0x10a, 0x123, 0x13e, 0x159, 0x175, 0x193, 0x1b1, 0x1d1, 0x1f1, 0x212, 0x235, 0x258, 0x27c, 0x2a0, 0x2c6, 0x2ed, 0x314, 0x33c, 0x365, 0x38e, 0x3b8, 0x3e3, 0x40e, 0x43a, 0x467, 0x494, 0x4c2, 0x4f0, 0x51f, 0x54e, 0x57d, 0x5ad, 0x5dd, 0x60e, 0x63f, 0x670, 0x6a1, 0x6d3, 0x705, 0x737, 0x769, 0x79b, 0x7cd, 0x800, 0x832, 0x864, 0x896, 0x8c8, 0x8fa, 0x92c, 0x95e, 0x98f, 0x9c0, 0x9f1, 0xa22, 0xa52, 0xa82, 0xab1, 0xae0, 0xb0f, 0xb3d, 0xb6b, 0xb98, 0xbc5, 0xbf1, 0xc1c, 0xc47, 0xc71, 0xc9a, 0xcc3, 0xceb, 0xd12, 0xd39, 0xd5f, 0xd83, 0xda7, 0xdca, 0xded, 0xe0e, 0xe2e, 0xe4e, 0xe6c, 0xe8a, 0xea6, 0xec1, 0xedc, 0xef5, 0xf0d, 0xf24, 0xf3a, 0xf4f, 0xf63, 0xf76, 0xf87, 0xf98, 0xfa7, 0xfb5, 0xfc2, 0xfcd, 0xfd8, 0xfe1, 0xfe9, 0xff0, 0xff5, 0xff9, 0xffd, 0xffe, - 0xfff, 0xffe, 0xffd, 0xff9, 0xff5, 0xff0, 0xfe9, 0xfe1, 0xfd8, 0xfcd, 0xfc2, 0xfb5, 0xfa7, 0xf98, 0xf87, 0xf76, 0xf63, 0xf4f, 0xf3a, 0xf24, 0xf0d, 0xef5, 0xedc, 0xec1, 0xea6, 0xe8a, 0xe6c, 0xe4e, 0xe2e, 0xe0e, 0xded, 0xdca, 0xda7, 0xd83, 0xd5f, 0xd39, 0xd12, 0xceb, 0xcc3, 0xc9a, 0xc71, 0xc47, 0xc1c, 0xbf1, 0xbc5, 0xb98, 0xb6b, 0xb3d, 0xb0f, 0xae0, 0xab1, 0xa82, 0xa52, 0xa22, 0x9f1, 0x9c0, 0x98f, 0x95e, 0x92c, 0x8fa, 0x8c8, 0x896, 0x864, 0x832, 0x800, 0x7cd, 0x79b, 0x769, 0x737, 0x705, 0x6d3, 0x6a1, 0x670, 0x63f, 0x60e, 0x5dd, 0x5ad, 0x57d, 0x54e, 0x51f, 0x4f0, 0x4c2, 0x494, 0x467, 0x43a, 0x40e, 0x3e3, 0x3b8, 0x38e, 0x365, 0x33c, 0x314, 0x2ed, 0x2c6, 0x2a0, 0x27c, 0x258, 0x235, 0x212, 0x1f1, 0x1d1, 0x1b1, 0x193, 0x175, 0x159, 0x13e, 0x123, 0x10a, 0xf2, 0xdb, 0xc5, 0xb0, 0x9c, 0x89, 0x78, 0x67, 0x58, 0x4a, 0x3d, 0x32, 0x27, 0x1e, 0x16, 0xf, 0xa, 0x6, 0x2, 0x1}; + 0xfff, 0xffe, 0xffd, 0xff9, 0xff5, 0xff0, 0xfe9, 0xfe1, 0xfd8, 0xfcd, 0xfc2, 0xfb5, 0xfa7, 0xf98, 0xf87, 0xf76, 0xf63, 0xf4f, 0xf3a, 0xf24, 0xf0d, 0xef5, 0xedc, 0xec1, 0xea6, 0xe8a, 0xe6c, 0xe4e, 0xe2e, 0xe0e, 0xded, 0xdca, 0xda7, 0xd83, 0xd5f, 0xd39, 0xd12, 0xceb, 0xcc3, 0xc9a, 0xc71, 0xc47, 0xc1c, 0xbf1, 0xbc5, 0xb98, 0xb6b, 0xb3d, 0xb0f, 0xae0, 0xab1, 0xa82, 0xa52, 0xa22, 0x9f1, 0x9c0, 0x98f, 0x95e, 0x92c, 0x8fa, 0x8c8, 0x896, 0x864, 0x832, 0x800, 0x7cd, 0x79b, 0x769, 0x737, 0x705, 0x6d3, 0x6a1, 0x670, 0x63f, 0x60e, 0x5dd, 0x5ad, 0x57d, 0x54e, 0x51f, 0x4f0, 0x4c2, 0x494, 0x467, 0x43a, 0x40e, 0x3e3, 0x3b8, 0x38e, 0x365, 0x33c, 0x314, 0x2ed, 0x2c6, 0x2a0, 0x27c, 0x258, 0x235, 0x212, 0x1f1, 0x1d1, 0x1b1, 0x193, 0x175, 0x159, 0x13e, 0x123, 0x10a, 0xf2, 0xdb, 0xc5, 0xb0, 0x9c, 0x89, 0x78, 0x67, 0x58, 0x4a, 0x3d, 0x32, 0x27, 0x1e, 0x16, 0xf, 0xa, 0x6, 0x2, 0x1, +}; #endif // AUDIO_DAC_SAMPLE_WAVEFORM_SINE #ifdef AUDIO_DAC_SAMPLE_WAVEFORM_TRIANGLE -static const dacsample_t dac_buffer_triangle[AUDIO_DAC_BUFFER_SIZE] = { +static const dacsample_t dac_buffer_triangle[] = { // 256 values, max 4095 0x0, 0x20, 0x40, 0x60, 0x80, 0xa0, 0xc0, 0xe0, 0x100, 0x120, 0x140, 0x160, 0x180, 0x1a0, 0x1c0, 0x1e0, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 0x300, 0x320, 0x340, 0x360, 0x380, 0x3a0, 0x3c0, 0x3e0, 0x400, 0x420, 0x440, 0x460, 0x480, 0x4a0, 0x4c0, 0x4e0, 0x500, 0x520, 0x540, 0x560, 0x580, 0x5a0, 0x5c0, 0x5e0, 0x600, 0x620, 0x640, 0x660, 0x680, 0x6a0, 0x6c0, 0x6e0, 0x700, 0x720, 0x740, 0x760, 0x780, 0x7a0, 0x7c0, 0x7e0, 0x800, 0x81f, 0x83f, 0x85f, 0x87f, 0x89f, 0x8bf, 0x8df, 0x8ff, 0x91f, 0x93f, 0x95f, 0x97f, 0x99f, 0x9bf, 0x9df, 0x9ff, 0xa1f, 0xa3f, 0xa5f, 0xa7f, 0xa9f, 0xabf, 0xadf, 0xaff, 0xb1f, 0xb3f, 0xb5f, 0xb7f, 0xb9f, 0xbbf, 0xbdf, 0xbff, 0xc1f, 0xc3f, 0xc5f, 0xc7f, 0xc9f, 0xcbf, 0xcdf, 0xcff, 0xd1f, 0xd3f, 0xd5f, 0xd7f, 0xd9f, 0xdbf, 0xddf, 0xdff, 0xe1f, 0xe3f, 0xe5f, 0xe7f, 0xe9f, 0xebf, 0xedf, 0xeff, 0xf1f, 0xf3f, 0xf5f, 0xf7f, 0xf9f, 0xfbf, 0xfdf, - 0xfff, 0xfdf, 0xfbf, 0xf9f, 0xf7f, 0xf5f, 0xf3f, 0xf1f, 0xeff, 0xedf, 0xebf, 0xe9f, 0xe7f, 0xe5f, 0xe3f, 0xe1f, 0xdff, 0xddf, 0xdbf, 0xd9f, 0xd7f, 0xd5f, 0xd3f, 0xd1f, 0xcff, 0xcdf, 0xcbf, 0xc9f, 0xc7f, 0xc5f, 0xc3f, 0xc1f, 0xbff, 0xbdf, 0xbbf, 0xb9f, 0xb7f, 0xb5f, 0xb3f, 0xb1f, 0xaff, 0xadf, 0xabf, 0xa9f, 0xa7f, 0xa5f, 0xa3f, 0xa1f, 0x9ff, 0x9df, 0x9bf, 0x99f, 0x97f, 0x95f, 0x93f, 0x91f, 0x8ff, 0x8df, 0x8bf, 0x89f, 0x87f, 0x85f, 0x83f, 0x81f, 0x800, 0x7e0, 0x7c0, 0x7a0, 0x780, 0x760, 0x740, 0x720, 0x700, 0x6e0, 0x6c0, 0x6a0, 0x680, 0x660, 0x640, 0x620, 0x600, 0x5e0, 0x5c0, 0x5a0, 0x580, 0x560, 0x540, 0x520, 0x500, 0x4e0, 0x4c0, 0x4a0, 0x480, 0x460, 0x440, 0x420, 0x400, 0x3e0, 0x3c0, 0x3a0, 0x380, 0x360, 0x340, 0x320, 0x300, 0x2e0, 0x2c0, 0x2a0, 0x280, 0x260, 0x240, 0x220, 0x200, 0x1e0, 0x1c0, 0x1a0, 0x180, 0x160, 0x140, 0x120, 0x100, 0xe0, 0xc0, 0xa0, 0x80, 0x60, 0x40, 0x20}; + 0xfff, 0xfdf, 0xfbf, 0xf9f, 0xf7f, 0xf5f, 0xf3f, 0xf1f, 0xeff, 0xedf, 0xebf, 0xe9f, 0xe7f, 0xe5f, 0xe3f, 0xe1f, 0xdff, 0xddf, 0xdbf, 0xd9f, 0xd7f, 0xd5f, 0xd3f, 0xd1f, 0xcff, 0xcdf, 0xcbf, 0xc9f, 0xc7f, 0xc5f, 0xc3f, 0xc1f, 0xbff, 0xbdf, 0xbbf, 0xb9f, 0xb7f, 0xb5f, 0xb3f, 0xb1f, 0xaff, 0xadf, 0xabf, 0xa9f, 0xa7f, 0xa5f, 0xa3f, 0xa1f, 0x9ff, 0x9df, 0x9bf, 0x99f, 0x97f, 0x95f, 0x93f, 0x91f, 0x8ff, 0x8df, 0x8bf, 0x89f, 0x87f, 0x85f, 0x83f, 0x81f, 0x800, 0x7e0, 0x7c0, 0x7a0, 0x780, 0x760, 0x740, 0x720, 0x700, 0x6e0, 0x6c0, 0x6a0, 0x680, 0x660, 0x640, 0x620, 0x600, 0x5e0, 0x5c0, 0x5a0, 0x580, 0x560, 0x540, 0x520, 0x500, 0x4e0, 0x4c0, 0x4a0, 0x480, 0x460, 0x440, 0x420, 0x400, 0x3e0, 0x3c0, 0x3a0, 0x380, 0x360, 0x340, 0x320, 0x300, 0x2e0, 0x2c0, 0x2a0, 0x280, 0x260, 0x240, 0x220, 0x200, 0x1e0, 0x1c0, 0x1a0, 0x180, 0x160, 0x140, 0x120, 0x100, 0xe0, 0xc0, 0xa0, 0x80, 0x60, 0x40, 0x20, +}; #endif // AUDIO_DAC_SAMPLE_WAVEFORM_TRIANGLE #ifdef AUDIO_DAC_SAMPLE_WAVEFORM_SQUARE -static const dacsample_t dac_buffer_square[AUDIO_DAC_BUFFER_SIZE] = { - [0 ... AUDIO_DAC_BUFFER_SIZE / 2 - 1] = AUDIO_DAC_OFF_VALUE, // first and - [AUDIO_DAC_BUFFER_SIZE / 2 ... AUDIO_DAC_BUFFER_SIZE - 1] = AUDIO_DAC_SAMPLE_MAX, // second half +static const dacsample_t dac_buffer_square[] = { + AUDIO_DAC_OFF_VALUE, // first and + AUDIO_DAC_SAMPLE_MAX, // second steps }; #endif // AUDIO_DAC_SAMPLE_WAVEFORM_SQUARE /* // four steps: 0, 1/3, 2/3 and 1 -static const dacsample_t dac_buffer_staircase[AUDIO_DAC_BUFFER_SIZE] = { - [0 ... AUDIO_DAC_BUFFER_SIZE/3 -1 ] = 0, - [AUDIO_DAC_BUFFER_SIZE / 4 ... AUDIO_DAC_BUFFER_SIZE / 2 -1 ] = AUDIO_DAC_SAMPLE_MAX / 3, - [AUDIO_DAC_BUFFER_SIZE / 2 ... 3 * AUDIO_DAC_BUFFER_SIZE / 4 -1 ] = 2 * AUDIO_DAC_SAMPLE_MAX / 3, - [3 * AUDIO_DAC_BUFFER_SIZE / 4 ... AUDIO_DAC_BUFFER_SIZE -1 ] = AUDIO_DAC_SAMPLE_MAX, +static const dacsample_t dac_buffer_staircase[] = { + 0, + AUDIO_DAC_SAMPLE_MAX / 3, + 2 * AUDIO_DAC_SAMPLE_MAX / 3, + AUDIO_DAC_SAMPLE_MAX, } */ #ifdef AUDIO_DAC_SAMPLE_WAVEFORM_TRAPEZOID -static const dacsample_t dac_buffer_trapezoid[AUDIO_DAC_BUFFER_SIZE] = {0x0, 0x1f, 0x7f, 0xdf, 0x13f, 0x19f, 0x1ff, 0x25f, 0x2bf, 0x31f, 0x37f, 0x3df, 0x43f, 0x49f, 0x4ff, 0x55f, 0x5bf, 0x61f, 0x67f, 0x6df, 0x73f, 0x79f, 0x7ff, 0x85f, 0x8bf, 0x91f, 0x97f, 0x9df, 0xa3f, 0xa9f, 0xaff, 0xb5f, 0xbbf, 0xc1f, 0xc7f, 0xcdf, 0xd3f, 0xd9f, 0xdff, 0xe5f, 0xebf, 0xf1f, 0xf7f, 0xfdf, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, - 0xfff, 0xfdf, 0xf7f, 0xf1f, 0xebf, 0xe5f, 0xdff, 0xd9f, 0xd3f, 0xcdf, 0xc7f, 0xc1f, 0xbbf, 0xb5f, 0xaff, 0xa9f, 0xa3f, 0x9df, 0x97f, 0x91f, 0x8bf, 0x85f, 0x7ff, 0x79f, 0x73f, 0x6df, 0x67f, 0x61f, 0x5bf, 0x55f, 0x4ff, 0x49f, 0x43f, 0x3df, 0x37f, 0x31f, 0x2bf, 0x25f, 0x1ff, 0x19f, 0x13f, 0xdf, 0x7f, 0x1f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; +static const dacsample_t dac_buffer_trapezoid[] = { + 0x0, 0x1f, 0x7f, 0xdf, 0x13f, 0x19f, 0x1ff, 0x25f, 0x2bf, 0x31f, 0x37f, 0x3df, 0x43f, 0x49f, 0x4ff, 0x55f, 0x5bf, 0x61f, 0x67f, 0x6df, 0x73f, 0x79f, 0x7ff, 0x85f, 0x8bf, 0x91f, 0x97f, 0x9df, 0xa3f, 0xa9f, 0xaff, 0xb5f, 0xbbf, 0xc1f, 0xc7f, 0xcdf, 0xd3f, 0xd9f, 0xdff, 0xe5f, 0xebf, 0xf1f, 0xf7f, 0xfdf, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfdf, 0xf7f, 0xf1f, 0xebf, 0xe5f, 0xdff, 0xd9f, 0xd3f, 0xcdf, 0xc7f, 0xc1f, 0xbbf, 0xb5f, 0xaff, 0xa9f, 0xa3f, 0x9df, 0x97f, 0x91f, 0x8bf, 0x85f, 0x7ff, 0x79f, 0x73f, 0x6df, 0x67f, 0x61f, 0x5bf, 0x55f, 0x4ff, 0x49f, 0x43f, 0x3df, 0x37f, 0x31f, 0x2bf, 0x25f, 0x1ff, 0x19f, 0x13f, 0xdf, 0x7f, 0x1f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +}; #endif // AUDIO_DAC_SAMPLE_WAVEFORM_TRAPEZOID static dacsample_t dac_buffer[AUDIO_DAC_BUFFER_SIZE]; @@ -124,20 +128,30 @@ __attribute__((weak)) uint16_t dac_value_generate(void) { uint_fast16_t value = 0; float frequency = 0.0f; +#if defined(AUDIO_DAC_SAMPLE_WAVEFORM_SINE) + const size_t wavetable_length = ARRAY_SIZE(dac_buffer_sine); +#elif defined(AUDIO_DAC_SAMPLE_WAVEFORM_TRIANGLE) + const size_t wavetable_length = ARRAY_SIZE(dac_buffer_triangle); +#elif defined(AUDIO_DAC_SAMPLE_WAVEFORM_TRAPEZOID) + const size_t wavetable_length = ARRAY_SIZE(dac_buffer_trapezoid); +#elif defined(AUDIO_DAC_SAMPLE_WAVEFORM_SQUARE) + const size_t wavetable_length = ARRAY_SIZE(dac_buffer_square); +#endif + for (size_t i = 0; i < active_tones_snapshot_length; i++) { /* Note: a user implementation does not have to rely on the active_tones_snapshot, but * could directly query the active frequencies through audio_get_processed_frequency */ frequency = active_tones_snapshot[i]; float new_dac_if = dac_if[i]; - new_dac_if += frequency * ((float)AUDIO_DAC_BUFFER_SIZE / AUDIO_DAC_SAMPLE_RATE * 2.0f / 3.0f); + new_dac_if += frequency * ((float)wavetable_length / AUDIO_DAC_SAMPLE_RATE * 2.0f / 3.0f); /*Note: the 2/3 are necessary to get the correct frequencies on the * DAC output (as measured with an oscilloscope), since the gpt * timer runs with 3*AUDIO_DAC_SAMPLE_RATE; and the DAC callback * is called twice per conversion.*/ - while (new_dac_if >= AUDIO_DAC_BUFFER_SIZE) - new_dac_if -= AUDIO_DAC_BUFFER_SIZE; + while (new_dac_if >= wavetable_length) + new_dac_if -= wavetable_length; dac_if[i] = new_dac_if; // Wavetable generation/lookup diff --git a/platforms/chibios/drivers/audio_pwm_hardware.c b/platforms/chibios/drivers/audio_pwm_hardware.c index 40d891326f..21b5c6892c 100644 --- a/platforms/chibios/drivers/audio_pwm_hardware.c +++ b/platforms/chibios/drivers/audio_pwm_hardware.c @@ -22,6 +22,12 @@ # define AUDIO_PWM_COUNTER_FREQUENCY 100000 #endif +#ifndef AUDIO_PWM_COMPLEMENTARY_OUTPUT +# define AUDIO_PWM_OUTPUT_MODE PWM_OUTPUT_ACTIVE_HIGH +#else +# define AUDIO_PWM_OUTPUT_MODE PWM_COMPLEMENTARY_OUTPUT_ACTIVE_HIGH +#endif + extern bool playing_note; extern bool playing_melody; extern uint8_t note_timbre; @@ -29,7 +35,7 @@ extern uint8_t note_timbre; static PWMConfig pwmCFG = {.frequency = AUDIO_PWM_COUNTER_FREQUENCY, /* PWM clock frequency */ .period = 2, .callback = NULL, - .channels = {[(AUDIO_PWM_CHANNEL - 1)] = {.mode = PWM_OUTPUT_ACTIVE_HIGH, .callback = NULL}}}; + .channels = {[(AUDIO_PWM_CHANNEL - 1)] = {.mode = AUDIO_PWM_OUTPUT_MODE, .callback = NULL}}}; static float channel_1_frequency = 0.0f; |