Compare commits

...

4 Commits

Author SHA1 Message Date
cnlohr 933a3d4347 Dual mode working 2024-10-09 01:05:35 -07:00
cnlohr 4c84e5e538 Working - full vector scope, no dual mode yet 2024-10-08 22:19:46 -07:00
cnlohr 01216baaf9 Update oscope code + autoreconnect in webpageo 2024-10-08 21:25:10 -07:00
cnlohr 9044689537 Middle before totally swapping to new mode 2024-10-08 19:50:22 -07:00
6 changed files with 304 additions and 177 deletions
+246 -154
View File
@@ -41,36 +41,66 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
**/ **/
// NOT LORA!!! -- but experimenting with the possibility of rx.
// SETUP INSTRUCTIONS: // SETUP INSTRUCTIONS:
// (1) `make` in the optionbytes folder to configure `RESET` correctly. // (1) `make` in the optionbytes folder to configure `RESET` correctly.
// (2) Create a tone (if using the funprog, ../ch32v003fun/minichlink/minichlink -X ECLK 1:235:189:9:3 for 27.48387097MHz // (2) Create a tone (if using the funprog, ../ch32v003fun/minichlink/minichlink -X ECLK 1:235:189:9:3 for 27.48387097MHz
// (2) or, for 24.387096762MHz - ../ch32v003fun/minichlink/minichlink -X ECLK 1:150:49:8:3 // (2) or, for 24.387096762MHz - ../ch32v003fun/minichlink/minichlink -X ECLK 1:150:49:8:3
/* More notes /* More notes
* Minimum sample time with DMA = fCPU / 28 (5.14MHz) * Minimum sample time with DMA = fCPU / 28 (5.14MHz)
*/ */
// TODO:
// 1: Cleanup some code.
// 2: Leverage other ADC.
// 3:
#include "ch32v003fun.h" #include "ch32v003fun.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <math.h> #include <math.h>
// Channel for ADC
#define CHANNEL 0
// For I2C, output will be on PB8/PB9 SCL/SDA
//#define ENABLE_OLED
//#define PWM_OUTPUT
int g_volume_pwm = 127; // 0 - 127 (100%) (but you can go over 100) (For when using PWM)
#define ENABLE_OLED_SCOPE
//#define PROFILING_PIN PC8
#define SAMPLETIME 1 // 0: 1.5 cycles; 1: 7.5 cycles; 2: 13.5 cycles; (0 would go fastest and is important in single-ADC mode, but 1 seems slightly better in 2-ADC mode)
#ifdef ENABLE_OLED_SCOPE
#define SH1107_128x128
#define SSD1306_RST_PIN PA3
#define SSD1306_CS_PIN PA4
#define SSD1306_DC_PIN PA6
#define SSD1306_MOSI_PIN PA7
#define SSD1306_SCK_PIN PA5
#define SSD1306_BAUD_RATE_PRESCALER SPI_BaudRatePrescaler_4
#include "ssd1306_spi.h"
#include "ssd1306.h"
#endif
#ifdef ENABLE_OLED
#define SH1107_128x128 #define SH1107_128x128
#define SSD1306_REMAP_I2C #define SSD1306_REMAP_I2C
//#define PWM_OUTPUT //#define SSD1306_I2C_IRQ
#define ENABLE_OLED
#define PROFILING_PIN PA0
#include "ssd1306_i2c.h" #include "ssd1306_i2c.h"
#include "ssd1306.h" #include "ssd1306.h"
#endif
#if defined( ENABLE_OLED ) && defined( ENABLE_OLED_SCOPE )
#error Cant be SPI and I2C OLED
#endif
#include "./usb_config.h" #include "./usb_config.h"
#include "../ch32v003fun/examples_v20x/otg_device/otgusb.h" #include "../ch32v003fun/examples_v20x/otg_device/otgusb.h"
@@ -79,78 +109,22 @@ SOFTWARE.
volatile uint16_t adc_buffer[ADC_BUFFSIZE]; volatile uint16_t adc_buffer[ADC_BUFFSIZE];
int g_volume_pwm = 127; // 0 - 127 (100%) (but you can go over 100)
int32_t g_goertzel_phasor_r = 32768; int32_t g_goertzel_phasor_r = 32768;
int32_t g_goertzel_phasor_i = 0; int32_t g_goertzel_phasor_i = 0;
int32_t g_goertzel_advance_r = 32768;
int32_t g_goertzel_advance_i = 0;
#if 0
int g_pwm_period = (30-1);
int g_goertzel_buffer = (752);
int g_exactcompute = (0);
int32_t g_goertzel_omega_per_sample = 2485087396; // 0.368351 of whole per step / 27.031915MHz
int32_t g_goertzel_coefficient = -1453756170;
int32_t g_goertzel_coefficient_s = 1580594514;
#endif
#if 1 #if 1
int g_pwm_period = (30-1); // Very basic setup, for tuning to 880AM
int g_goertzel_buffer = (180); int g_pwm_period = (60-1);
int g_exactcompute = (0); int g_exactcompute = (1);
int32_t g_goertzel_omega_per_sample = 5509657063; // 0.816667 of whole per step / 0.880000MHz int g_goertzel_buffer = (1024);
int32_t g_goertzel_omega_per_sample = 873460290; // 0.183333 of whole per step / -8.720000MHz
int32_t g_goertzel_coefficient = 873460290; int32_t g_goertzel_coefficient = 873460290;
int32_t g_goertzel_coefficient_s = -1961823932; int32_t g_goertzel_coefficient_s = 1961823932;
int32_t g_goertzel_advance_r = -3425;
int32_t g_goertzel_advance_i = 32588;
#endif #endif
#if 0
int g_pwm_period = (31-1);
int g_goertzel_buffer = (412);
int g_exactcompute = (0);
const int32_t g_goertzel_omega_per_sample = 1670254667; // 0.247573 of whole per step / 1.150016MHz
const int32_t g_goertzel_coefficient = 32748822;
const int32_t g_goertzel_coefficient_s = 2147233926;
#endif
#if 0
int g_pwm_period = (30-1);
int g_goertzel_buffer = (576);
int g_exactcompute = (0);
int32_t g_goertzel_omega_per_sample = 1264972285; // 0.187500 of whole per step / 90.300000MHz
int32_t g_goertzel_coefficient = 821806413;
int32_t g_goertzel_coefficient_s = 1984016189;
#endif
#if 0
int g_pwm_period = (30-1);
int g_goertzel_buffer = (320);
int g_exactcompute = (0);
const int32_t g_goertzel_omega_per_sample = 990894956; // 0.146875 of whole per step / 101.505000MHz
const int32_t g_goertzel_coefficient = 1296126516;
const int32_t g_goertzel_coefficient_s = 1712233066;
#endif
#if 0
int g_pwm_period = (30-1);
int g_goertzel_buffer = (384);
int g_exactcompute = (0);
const int32_t g_goertzel_omega_per_sample = 4251712402; // 0.630208 of whole per step / 27.025000MHz
const int32_t g_goertzel_coefficient = -1468003291;
const int32_t g_goertzel_coefficient_s = -1567371161;
#endif
#if 0
int g_pwm_period = (30-1);
int g_goertzel_buffer = (336);
int g_exactcompute = (0);
const int32_t g_goertzel_omega_per_sample = 1827182189; // 0.270833 of whole per step / 89.900000MHz
const int32_t g_goertzel_coefficient = -280302863;
const int32_t g_goertzel_coefficient_s = 2129111628;
#endif
int intensity_average = 1; int intensity_average = 1;
#define LOG_GOERTZEL_LIST 512 #define LOG_GOERTZEL_LIST 512
@@ -162,49 +136,59 @@ void SetupADC()
// XXX TODO -look into PGA // XXX TODO -look into PGA
// XXX TODO - Look into tag-teaming the ADCs // XXX TODO - Look into tag-teaming the ADCs
// PDA is analog input chl 7 // PDA is analog input chl CHANNEL
GPIOA->CFGLR &= ~(0xf<<(4*7)); // CNF = 00: Analog, MODE = 00: Input GPIOA->CFGLR &= ~(0xf<<(4*CHANNEL)); // CNF = 00: Analog, MODE = 00: Input
// ADC CLK is chained off of APB2. // ADC CLK is chained off of APB2.
// Reset the ADC to init all regs // Reset the ADC to init all regs
RCC->APB2PRSTR |= RCC_APB2Periph_ADC1; RCC->APB2PRSTR |= RCC_APB2Periph_ADC1 | RCC_APB2Periph_ADC2;
RCC->APB2PRSTR &= ~RCC_APB2Periph_ADC1; RCC->APB2PRSTR &= ~( RCC_APB2Periph_ADC1 | RCC_APB2Periph_ADC2 );
// ADCCLK = 12 MHz => RCC_ADCPRE divide by 4 // ADCCLK = 12 MHz => RCC_ADCPRE divide by 4
RCC->CFGR0 &= ~RCC_ADCPRE; // Clear out the bis in case they were set RCC->CFGR0 &= ~RCC_ADCPRE; // Clear out the bis in case they were set
RCC->CFGR0 |= RCC_ADCPRE_DIV2; // Fastest possible (divide-by-2) NOTE: This is OUTSIDE the specified value in the datasheet. RCC->CFGR0 |= RCC_ADCPRE_DIV2; // Fastest possible (divide-by-2) NOTE: This is OUTSIDE the specified value in the datasheet.
// Set up single conversion on chl 7 // Set up single conversion on chl 7
ADC1->RSQR1 = 0; ADC1->RSQR3 = CHANNEL; // 0-9 for 8 ext inputs and two internals Set to 7 for PA7
ADC1->RSQR2 = 0; ADC2->RSQR3 = CHANNEL; // 0-9 for 8 ext inputs and two internals Set to 7 for PA7
ADC1->RSQR3 = 7; // 0-9 for 8 ext inputs and two internals
ADC1->ISQR = CHANNEL; // Mirror in case we switch to injection mode.
ADC2->ISQR = CHANNEL;
// Not using injection group. // Not using injection group.
// Sampling time for channels. Careful: This has PID tuning implications. // Sampling time for channels. Careful: This has PID tuning implications.
// Note that with 3 and 3,the full loop (and injection) runs at 138kHz. // Note that with 3 and 3,the full loop (and injection) runs at 138kHz.
ADC1->SAMPTR2 = (0<<(3*7)); ADC1->SAMPTR2 = (SAMPLETIME<<(3*CHANNEL)); // (3*channel)
ADC2->SAMPTR2 = (SAMPLETIME<<(3*CHANNEL)); // (3*channel)
// Turn on ADC and set rule group to sw trig // Turn on ADC and set rule group to sw trig
// 0 = Use TRGO event for Timer 1 to fire ADC rule. // 0 = Use TRGO event for Timer 1 to fire ADC rule.
ADC1->CTLR2 = ADC_ADON | ADC_EXTTRIG | ADC_DMA; ADC1->CTLR2 = ADC_ADON | ADC_EXTTRIG | ADC_DMA;
ADC2->CTLR2 = ADC_ADON | ADC_EXTTRIG | ADC_EXTSEL_1;// | ADC_DMA;
// For EXTTRIG, EXTSEL (none) = 0 = TIM1CC1 /
// For JEXTTRIG, EXTSEL = 0 = TIM1 TRGO (Or ADC_JEXTSEL_0 => CH4)
// Reset calibration // Reset calibration
ADC1->CTLR2 |= ADC_RSTCAL; ADC1->CTLR2 |= ADC_RSTCAL;
ADC2->CTLR2 |= ADC_RSTCAL;
while(ADC1->CTLR2 & ADC_RSTCAL); while(ADC1->CTLR2 & ADC_RSTCAL);
while(ADC2->CTLR2 & ADC_RSTCAL);
// Calibrate ADC // Calibrate ADC
ADC1->CTLR2 |= ADC_CAL; ADC1->CTLR2 |= ADC_CAL;
ADC2->CTLR2 |= ADC_CAL;
while(ADC1->CTLR2 & ADC_CAL); while(ADC1->CTLR2 & ADC_CAL);
while(ADC2->CTLR2 & ADC_CAL);
// ADC_SCAN: Allow scanning. // ADC_SCAN: Allow scanning.
ADC2->CTLR1 = ADC_SCAN;
ADC1->CTLR1 = ADC1->CTLR1 =
//ADC_SCAN; //ADC_DUALMOD_0 | ADC_DUALMOD_3 | // Alternate Trigger Mode (Can't use with DMA)
ADC_SCAN | ADC_BUFEN ; ADC_SCAN;
//ADC_Pga_16 | ADC_SCAN | ADC_BUFEN ; //ADC_Pga_16 | ADC_BUFEN ;
//ADC_Pga_64 | ADC_SCAN; //ADC_Pga_64 | ADC_BUFEN;
// Turn on DMA // Turn on DMA
RCC->AHBPCENR |= RCC_AHBPeriph_DMA1; RCC->AHBPCENR |= RCC_AHBPeriph_DMA1;
@@ -212,32 +196,21 @@ void SetupADC()
//DMA1_Channel1 is for ADC //DMA1_Channel1 is for ADC
DMA1_Channel1->PADDR = (uint32_t)&ADC1->RDATAR; DMA1_Channel1->PADDR = (uint32_t)&ADC1->RDATAR;
DMA1_Channel1->MADDR = (uint32_t)adc_buffer; DMA1_Channel1->MADDR = (uint32_t)adc_buffer;
DMA1_Channel1->CNTR = ADC_BUFFSIZE; DMA1_Channel1->CNTR = ADC_BUFFSIZE/2;
DMA1_Channel1->CFGR = DMA1_Channel1->CFGR =
DMA_M2M_Disable | DMA_M2M_Disable |
DMA_Priority_VeryHigh | DMA_Priority_VeryHigh |
DMA_MemoryDataSize_HalfWord | DMA_MemoryDataSize_Word |
DMA_PeripheralDataSize_HalfWord | DMA_PeripheralDataSize_Word |
DMA_MemoryInc_Enable | DMA_MemoryInc_Enable |
DMA_Mode_Circular | DMA_Mode_Circular |
DMA_DIR_PeripheralSRC; DMA_DIR_PeripheralSRC;
// NVIC_SetPriority( DMA1_Channel1_IRQn, 0<<4 ); //We don't need to tweak priority.
NVIC_EnableIRQ( DMA1_Channel1_IRQn ); NVIC_EnableIRQ( DMA1_Channel1_IRQn );
DMA1_Channel1->CFGR |= DMA_CFGR1_EN | DMA_IT_TC | DMA_IT_HT; // Transmission Complete + Half Empty Interrupts. DMA1_Channel1->CFGR |= DMA_CFGR1_EN | DMA_IT_TC | DMA_IT_HT; // Transmission Complete + Half Empty Interrupts.
// Turn on DMA channel 1
DMA1_Channel1->CFGR |= DMA_CFGR1_EN;
// Enable continuous conversion and DMA // Enable continuous conversion and DMA
ADC1->CTLR2 |= ADC_DMA; // | ADC_CONT; ADC1->CTLR2 |= ADC_DMA; // | ADC_CONT;
// start conversion
ADC1->CTLR2 |= ADC_SWSTART;// | ADC_CONT;
} }
static void SetupTimer1() static void SetupTimer1()
@@ -261,18 +234,80 @@ static void SetupTimer1()
TIM1->BDTR |= 0xc000;//TIM_MOE; TIM1->BDTR |= 0xc000;//TIM_MOE;
#endif #endif
TIM1->CCER |= TIM_CC1E; TIM1->CCER |= TIM_CC1E | TIM_CC4E | TIM_CC3E;
TIM1->CHCTLR1 |= TIM_OC1M_2 | TIM_OC1M_1; TIM1->CHCTLR1 |= TIM_OC1M_2 | TIM_OC1M_1;
TIM1->CH1CVR = 1; TIM1->CHCTLR2 |= TIM_OC3M_2 | TIM_OC3M_1 | TIM_OC4M_2 | TIM_OC4M_1;
TIM1->CH1CVR = 1; // In case we are using rule triggering
TIM1->CH3CVR = 1; // In case we are using rule (alternate) triggering
TIM1->CH4CVR = 1; // In case we are using injection triggering
// Setup TRGO to trigger for ADC (NOTE: Not on the 203! TIM1_TRGO is only connected to injection) // Setup TRGO to trigger for ADC injection group
//TIM1->CTLR2 = TIM_MMS_1; TIM1->CTLR2 = TIM_MMS_1;
// Enable TIM1 outputs // Enable TIM1 outputs
TIM1->BDTR = TIM_MOE; TIM1->BDTR = TIM_MOE;
TIM1->CTLR1 = TIM_CEN; TIM1->CTLR1 = TIM_CEN;
} }
#ifdef ENABLE_OLED_SCOPE
// Command-mode, Set X, Disable Timer, Set Y, Enable Timer
// Done this way to prevent streaking.
uint8_t cmdxy[] = { 0x00, 0xd3, 0x30, 0xd5, 0xff, 0x00, 0xdc, 0x30, 0xd5, 0xf0 };
void config_turbo_scope()
{
DMA1_Channel3->PADDR = (uint32_t)&SPI1->DATAR;
DMA1_Channel3->MADDR = (uint32_t)cmdxy;
DMA1_Channel3->CNTR = sizeof(cmdxy);
DMA1_Channel3->CFGR =
DMA_M2M_Disable |
DMA_Priority_Low |
DMA_MemoryDataSize_Byte |
DMA_PeripheralDataSize_Byte |
DMA_MemoryInc_Enable |
DMA_Mode_Normal |
DMA_DIR_PeripheralDST;
// Turn on DMA channel 3
DMA1_Channel3->CFGR |= DMA_CFGR1_EN;
funDigitalWrite( SSD1306_DC_PIN, FUN_LOW );
SPI1->CTLR2 |= SPI_CTLR2_TXDMAEN;
}
void ssd1306_send_turbo(uint8_t *data, uint8_t sz)
{
funDigitalWrite( SSD1306_DC_PIN, FUN_LOW );
funDigitalWrite( SSD1306_CS_PIN, FUN_LOW );
// send data
while(sz--)
{
// wait for TXE
while(!(SPI1->STATR & SPI_STATR_TXE));
// Send byte
SPI1->DATAR = *data++;
}
// wait for not busy before exiting
while(SPI1->STATR & SPI_STATR_BSY);
funDigitalWrite( SSD1306_CS_PIN, FUN_HIGH );
}
static void PlotPoint( int x, int y )
{
funDigitalWrite( SSD1306_CS_PIN, FUN_HIGH );
cmdxy[2] = x; cmdxy[7] = y;
DMA1_Channel3->CNTR = sizeof(cmdxy);
funDigitalWrite( SSD1306_CS_PIN, FUN_LOW );
DMA1_Channel3->CFGR |= DMA_CFGR1_EN;
}
#endif
void InnerLoop() __attribute__((noreturn)); void InnerLoop() __attribute__((noreturn));
@@ -319,7 +354,9 @@ void DMA1_Channel1_IRQHandler( void )
// Clear all possible flags. // Clear all possible flags.
DMA1->INTFCR = DMA1_IT_GL1; DMA1->INTFCR = DMA1_IT_GL1;
int tpl = ADC_BUFFSIZE - DMA1_Channel1->CNTR; // Warning, sometimes this is == to the base, or == 0 (i.e. might be 256, if top is 255) int tpl = ADC_BUFFSIZE - DMA1_Channel1->CNTR*2;
// Warning, sometimes this is DMA1_Channel1->CNTR == to the base, or == 0 (i.e. might be 256, if top is 255)
tpl += ADC_BUFFSIZE; tpl += ADC_BUFFSIZE;
tpl = (tpl & (ADC_BUFFSIZE-1)); tpl = (tpl & (ADC_BUFFSIZE-1));
if( tpl == ADC_BUFFSIZE ) tpl = 0; if( tpl == ADC_BUFFSIZE ) tpl = 0;
@@ -338,6 +375,9 @@ void DMA1_Channel1_IRQHandler( void )
// Here is where the magic happens. // Here is where the magic happens.
#if 1 #if 1
// Also, this is the current limiting factor for the maximum samplerate.
// We can't go above 7.2MSPS and keep up here when main CPU is @ 144MHz.
#define XSTR(x) #x #define XSTR(x) #x
#define GOERTZELLOOP(idx) \ #define GOERTZELLOOP(idx) \
asm volatile("\n\ asm volatile("\n\
@@ -421,8 +461,9 @@ void DMA1_Channel1_IRQHandler( void )
} }
// Now, rotate rr, ri by that phasor. // Now, rotate rr, ri by that phasor.
temp = (g_goertzel_phasor_r * ri + g_goertzel_phasor_i * rr) >> 15; // To get it in line >> 15, but we also want to divide by 8 (>>3) because that makes the rest of the math easier.
rr = (g_goertzel_phasor_r * rr - g_goertzel_phasor_i * ri) >> 15; temp = (g_goertzel_phasor_r * ri + g_goertzel_phasor_i * rr) >> (15+3);
rr = (g_goertzel_phasor_r * rr - g_goertzel_phasor_i * ri) >> (15+3);
ri = temp; ri = temp;
// rr, ri are now in the correct frame of reference. Continue computing. // rr, ri are now in the correct frame of reference. Continue computing.
@@ -430,9 +471,6 @@ void DMA1_Channel1_IRQHandler( void )
qibaselogs[qibaselogs_head] = ((uint16_t)rr) | (((uint16_t)ri)<<16); qibaselogs[qibaselogs_head] = ((uint16_t)rr) | (((uint16_t)ri)<<16);
qibaselogs_head = ( qibaselogs_head + 1 ) & ((LOG_GOERTZEL_LIST)-1); qibaselogs_head = ( qibaselogs_head + 1 ) & ((LOG_GOERTZEL_LIST)-1);
rr>>=2;
ri>>=2;
int s = rr * rr + ri * ri; int s = rr * rr + ri * ri;
//int intensity = 1<<( ( 32 - __builtin_clz(s) )/2); //int intensity = 1<<( ( 32 - __builtin_clz(s) )/2);
#define ABS(x) (((x)<0)?-(x):(x)) #define ABS(x) (((x)<0)?-(x):(x))
@@ -442,6 +480,10 @@ void DMA1_Channel1_IRQHandler( void )
intensity++; intensity++;
intensity = (intensity + s/intensity)/2; intensity = (intensity + s/intensity)/2;
intensity = (intensity + s/intensity)/2; intensity = (intensity + s/intensity)/2;
// intensity = rr * rr + ri * ri
// This performs a low-pass IIR without exploding intensity_average.
intensity_average = intensity_average - (intensity_average>>12) + (intensity>>6); intensity_average = intensity_average - (intensity_average>>12) + (intensity>>6);
#ifdef PWM_OUTPUT #ifdef PWM_OUTPUT
@@ -460,6 +502,18 @@ void DMA1_Channel1_IRQHandler( void )
adc_offset -= accumulate_over_window / g_goertzel_buffer; adc_offset -= accumulate_over_window / g_goertzel_buffer;
accumulate_over_window = 0; accumulate_over_window = 0;
#ifdef ENABLE_OLED_SCOPE
int rrplot = rr * 1536 / (intensity_average);
int riplot = ri * 1536 / (intensity_average);
rrplot += 64;
riplot += 64;
if( rrplot < 1 ) rrplot = 1;
if( riplot < 1 ) riplot = 1;
if( rrplot > 126 ) rrplot = 126;
if( riplot > 126 ) riplot = 126;
PlotPoint( rrplot, riplot );
#endif
#ifdef PROFILING_PIN #ifdef PROFILING_PIN
funDigitalWrite( PROFILING_PIN, 1 ); funDigitalWrite( PROFILING_PIN, 1 );
#endif #endif
@@ -492,7 +546,6 @@ static inline uint32_t gets2()
return ret; return ret;
} }
void InnerLoop() void InnerLoop()
{ {
while(1){ while(1){
@@ -507,13 +560,12 @@ void InnerLoop()
} }
#endif #endif
int pxa = 0;
// Only display half of the list so the other half could // Only display half of the list so the other half could
// be updated by the ISR. // be updated by the ISR.
int glread = qibaselogs_head;
int intensity = 0; #ifdef ENABLE_OLED
int pxa = 0;
int glread = qibaselogs_head;
for( pxa = 0; pxa < LOG_GOERTZEL_LIST; pxa++ ) for( pxa = 0; pxa < LOG_GOERTZEL_LIST; pxa++ )
{ {
@@ -534,12 +586,8 @@ void InnerLoop()
if( rr > 127 ) rr = 127; if( rr > 127 ) rr = 127;
if( ri > 127 ) ri = 127; if( ri > 127 ) ri = 127;
#ifdef ENABLE_OLED
ssd1306_drawPixel( rr, ri, 1 ); ssd1306_drawPixel( rr, ri, 1 );
#endif
} }
#ifdef ENABLE_OLED
//char cts[32]; //char cts[32];
//snprintf( cts, 32, "%d", intensity_average ); //snprintf( cts, 32, "%d", intensity_average );
//ssd1306_drawstr( 0, 0, cts, 1 ); //ssd1306_drawstr( 0, 0, cts, 1 );
@@ -550,20 +598,43 @@ void InnerLoop()
//if( ik == sizeof(ssd1306_buffer) ) ik = 0; //if( ik == sizeof(ssd1306_buffer) ) ik = 0;
ssd1306_setbuf(0); ssd1306_setbuf(0);
#else
Delay_Ms(17);
#endif #endif
// printf( "%6d %8d %8d - %8d %8d - %8d\n", g_goertzel_outs,g_goertzelp2_store, g_goertzelp_store, rr, ri, x ); // Do nothing.
Delay_Ms(17);
// Delay_Ms(940);
//printf( "!!!!\n ");
} }
} }
uint8_t i2c_send_buffer[16];
void setup_i2c_dma(void)
{
// Turn on DMA
RCC->AHBPCENR |= RCC_AHBPeriph_DMA1;
//DMA1_Channel6 is for I2C1TX
DMA1_Channel6->PADDR = (uint32_t)&I2C1->DATAR;
DMA1_Channel6->MADDR = (uint32_t)&i2c_send_buffer;
DMA1_Channel6->CNTR = 0;
DMA1_Channel6->CFGR =
DMA_M2M_Disable |
DMA_Priority_Low |
DMA_MemoryDataSize_Byte |
DMA_PeripheralDataSize_Byte |
DMA_MemoryInc_Enable |
DMA_Mode_Normal |
DMA_DIR_PeripheralDST |
0;
I2C1->CTLR2 = I2C_CTLR2_DMAEN | 0b111100;
DMA1_Channel6->CFGR |= DMA_CFGR1_EN;
NVIC_DisableIRQ(I2C1_EV_IRQn);
printf( "INTO\n" );
}
int main() int main()
{ {
SystemInit(); SystemInit();
@@ -604,7 +675,7 @@ int main()
SetupADC(); SetupADC();
#ifdef ENABLE_OLED #if defined( ENABLE_OLED )
ssd1306_i2c_setup(); ssd1306_i2c_setup();
ssd1306_i2c_init(); ssd1306_i2c_init();
@@ -617,32 +688,49 @@ int main()
ssd1306_refresh(); ssd1306_refresh();
#endif #endif
#if 0 #ifdef ENABLE_OLED_SCOPE
int i = 0; int i;
int k = 0;
int frame = 0; ssd1306_spi_init();
while( 1) ssd1306_rst();
{
// ssd1306_drawLine( (frame)%128, (0)%128, (0)%128, (127-frame)%128, 1 ); if( ssd1306_init() )
ssd1306_drawstr( frame%128, frame%128, "hello", 1 ); printf( "Failed to initialize OLED\n" );
else
printf( "Initialized OLED\n" );
ssd1306_refresh();
ssd1306_setbuf(0); ssd1306_setbuf(0);
frame++;
// Setup a diagonal to allow for vector mode.
for( i = 0; i < 128; i++ )
{
ssd1306_drawPixel( i, i, 1 );
//ssd1306_drawPixel( i+1, i, 1 );
} }
while(1); ssd1306_refresh();
uint8_t force_two_row_mode[] = {
0xa8, 0, // Set MUX ratio (Actually # of lines to scan) (But it's this + 1) You can make this 1 for wider.
};
ssd1306_pkt_send(force_two_row_mode, sizeof( force_two_row_mode ) , 1);
uint8_t force_max_speed[] = {
0xd5, 0xf0
};
ssd1306_pkt_send(force_max_speed, sizeof( force_max_speed ) , 1);
config_turbo_scope();
#if 0 // Test streaking
int rframe = 0;
while(1)
{
PlotPoint( rframe & 0xff, rframe>>8 );
rframe++;
//Delay_Ms(1);
}
#endif #endif
#if 0
// turn on the op-amp
EXTEN->EXTEN_CTR |= EXTEN_OPA_EN;
// select op-amp pos pin: 0 = PA2, 1 = PD7
EXTEN->EXTEN_CTR |= EXTEN_OPA_PSEL;
// select op-amp neg pin: 0 = PA1, 1 = PD0
EXTEN->EXTEN_CTR |= EXTEN_OPA_NSEL;
#endif #endif
#ifdef PROFILING_PIN #ifdef PROFILING_PIN
@@ -743,7 +831,7 @@ void HandleHidUserReportOutComplete( struct _USBState * ctx )
uint32_t * configs = (uint32_t*)scratchpad; uint32_t * configs = (uint32_t*)scratchpad;
// Note: configs[0] == 0xac (command type) // Note: configs[0] == 0xac (command type)
printf( "Is Configure Packet %08x\n", configs[1] ); //printf( "Is Configure Packet %08x\n", configs[1] );
int numconfigs = configs[1]; int numconfigs = configs[1];
if( numconfigs > 0) g_pwm_period = configs[2]; if( numconfigs > 0) g_pwm_period = configs[2];
@@ -762,13 +850,13 @@ void HandleHidUserReportOutComplete( struct _USBState * ctx )
// Consider using PGA. // Consider using PGA.
//ADC_Pga_16 | ADC_SCAN | ADC_BUFEN ; //ADC_Pga_16 | ADC_SCAN | ADC_BUFEN ;
//ADC_Pga_64 | ADC_SCAN; //ADC_Pga_64 | ADC_SCAN;
ADC1->CTLR1 = ADC1->CTLR1 |= ADC_BUFEN;// | ADC_Pga_4; // Adding PGA causes wild oscillation.
ADC_SCAN | ADC_BUFEN; ADC1->CTLR2 |= ADC_BUFEN;// | ADC_Pga_4;
} }
else else
{ {
ADC1->CTLR1 = ADC1->CTLR1 &= (~ADC_BUFEN);
ADC_SCAN; ADC2->CTLR1 &= (~ADC_BUFEN);
} }
} }
@@ -776,6 +864,10 @@ void HandleHidUserReportOutComplete( struct _USBState * ctx )
g_goertzel_samples = 0; g_goertzel_samples = 0;
TIM1->ATRLR = g_pwm_period; TIM1->ATRLR = g_pwm_period;
TIM1->CH1CVR = 1;
TIM1->CH3CVR = TIM1->ATRLR/2+1;
g_isConfigurePacket = 0; g_isConfigurePacket = 0;
} }
return; return;
+41 -7
View File
@@ -22,6 +22,7 @@ function DrawSpan( rowspan, colspan, freq, target, docolor, extrastr = "" )
return ret; return ret;
} }
var system_rate = 288000000; // in MHz for effective ADC (note: This can be 2x normal clock if in dual ADC mode)
var lastGn; var lastGn;
var lastGmhz; var lastGmhz;
var lastGfr; var lastGfr;
@@ -62,7 +63,7 @@ function SendGoertz()
var g_exactcompute = exact_compute; var g_exactcompute = exact_compute;
textarea.value = textarea.value =
"int g_pwm_period = ("+n+"-1);\n" + "int g_pwm_period = ("+n+"-1); // " + system_rate/lastGn/1000000. + " MHz Samplerate\n" +
"int g_exactcompute = ("+exact_compute+");\n" + "int g_exactcompute = ("+exact_compute+");\n" +
"int g_goertzel_buffer = ("+brf+");\n" + "int g_goertzel_buffer = ("+brf+");\n" +
"int32_t g_goertzel_omega_per_sample = " + g_goertzel_coefficient.toFixed(0) + "; // " + ( omega / (3.1415926535*2.0)).toFixed(6) + " of whole per step / " + mhz.toFixed(6) + "MHz\n" + "int32_t g_goertzel_omega_per_sample = " + g_goertzel_coefficient.toFixed(0) + "; // " + ( omega / (3.1415926535*2.0)).toFixed(6) + " of whole per step / " + mhz.toFixed(6) + "MHz\n" +
@@ -95,6 +96,7 @@ function SendGoertz()
for( var i = 0|0; i < 10; i++ ) for( var i = 0|0; i < 10; i++ )
{ {
var tc = (tz / 1000000000.0) % 10; var tc = (tz / 1000000000.0) % 10;
if( document.getElementById( "mhzm" + i ) )
document.getElementById( "mhzm" + i ).value = tc|0; document.getElementById( "mhzm" + i ).value = tc|0;
tz *= 10; tz *= 10;
} }
@@ -131,6 +133,8 @@ function mhzm( event, ths )
let goertzel2 = document.getElementById("GOERTZEL2").checked; let goertzel2 = document.getElementById("GOERTZEL2").checked;
let quanta = Math.round(Number(document.getElementById("quanta").value)); let quanta = Math.round(Number(document.getElementById("quanta").value));
let quantasearch = Math.round(Number(document.getElementById("quantasearch").value)); let quantasearch = Math.round(Number(document.getElementById("quantasearch").value));
SaveDefaults();
system_rate = xtal *1000000;
let n = lastGn; let n = lastGn;
let freq = ( xtal / n ); let freq = ( xtal / n );
@@ -167,7 +171,7 @@ function computeTable()
let goertzel2 = document.getElementById("GOERTZEL2").checked; let goertzel2 = document.getElementById("GOERTZEL2").checked;
let quanta = Math.round(Number(document.getElementById("quanta").value)); let quanta = Math.round(Number(document.getElementById("quanta").value));
let quantasearch = Math.round(Number(document.getElementById("quantasearch").value)); let quantasearch = Math.round(Number(document.getElementById("quantasearch").value));
SaveDefaults();
const max_harmonics = 28|0; const max_harmonics = 28|0;
const min_harmonics = (quadrature?1:0)|0; const min_harmonics = (quadrature?1:0)|0;
@@ -206,6 +210,7 @@ function computeTable()
if( goertzels || quadrature ) if( goertzels || quadrature )
{ {
contents += "<input type=checkbox ID=toggle_adc_buffer onchange='toggleBuffer(this)'><label for=toggle_buffer>ADC Buffer Enable</label><BR>Scroll Wheel Control:<BR>";
contents += "<TABLE BORDER=1>"; contents += "<TABLE BORDER=1>";
contents += '<TR><TH>d\\h</div></TH>'; contents += '<TR><TH>d\\h</div></TH>';
for( let h = 0|min_harmonics; h <= max_harmonics; h++ ) for( let h = 0|min_harmonics; h <= max_harmonics; h++ )
@@ -279,7 +284,7 @@ function computeTable()
if( mode == 0 ) if( mode == 0 )
{ {
contents += "<TD COLSPAN=2>" contents += "<TD COLSPAN=2>"
if( tgoertzelp == h ) contents += "<SPAN ONCLICK='Goertz(" + n + ", " + freq * (h+goertzelpoint) + ", " + (goertzelpoint) + ", " + quantaA + ", 0)'>↑" + (goertzelpoint).toFixed(6) + "</SPAN>"; if( tgoertzelp == h ) contents += "<INPUT TYPE=SUBMIT ONCLICK='Goertz(" + n + ", " + freq * (h+goertzelpoint) + ", " + (goertzelpoint) + ", " + quantaA + ", 0)' VALUE='↑" + (goertzelpoint).toFixed(6) + "'/>";
contents += "</TD>"; contents += "</TD>";
} }
else if( mode == 1 ) else if( mode == 1 )
@@ -289,7 +294,7 @@ function computeTable()
else if( mode == 2 ) else if( mode == 2 )
{ {
contents += "<TD COLSPAN=2>" contents += "<TD COLSPAN=2>"
if( tgoertzelpi == h-1 ) contents += "<SPAN ONCLICK='Goertz(" + n + ", " + freq * (h-goertzelpointinv) + ", " + goertzelpointinv + ", " + quantaINV + ", 0)'>↓" + goertzelpointinv.toFixed(6) + "</SPAN>"; if( tgoertzelpi == h-1 ) contents += "<INPUT TYPE=SUBMIT ONCLICK='Goertz(" + n + ", " + freq * (h-goertzelpointinv) + ", " + goertzelpointinv + ", " + quantaINV + ", 0)' VALUE='↓" + goertzelpointinv.toFixed(6) + "'/>";
contents += "</TD>"; contents += "</TD>";
} }
else if( mode == 3 ) else if( mode == 3 )
@@ -328,7 +333,7 @@ function computeTable()
contents += "<TH COLSPAN=1>" + h + "</TH>"; contents += "<TH COLSPAN=1>" + h + "</TH>";
} }
for( let n = 0|28; n <= 96; n++ ) for( let n = 0|28; n <= 96; n+=2 )
{ {
let freq = ( xtal / n ); let freq = ( xtal / n );
let goertzelpoint = 0; let goertzelpoint = 0;
@@ -358,7 +363,7 @@ function computeTable()
if( rid == 0 ) if( rid == 0 )
{ {
contents += "<TD COLSPAN=1 ROWSPAN=2>" contents += "<TD COLSPAN=1 ROWSPAN=2>"
contents += "<SPAN ONCLICK='Goertz(" + n + ", " + freq * (h+tgoertzelpoint) + ", " + (tgoertzelpoint) + ", " + quantaA + ", 1)'>↑" + n + "</SPAN>"; contents += "<INPUT TYPE=SUBMIT ONCLICK='Goertz(" + n + ", " + freq * (h+tgoertzelpoint) + ", " + (tgoertzelpoint) + ", " + quantaA + ", 1)' VALUE='↑" + n + "'/>";
contents += "</TD>" contents += "</TD>"
} }
} }
@@ -386,8 +391,37 @@ function computeTable()
document.getElementById( "TABLE" ).innerHTML = contents; document.getElementById( "TABLE" ).innerHTML = contents;
} }
const savedFields = ["crystalmhz", "targetmhz", "QUADRATURE", "GOERTZELS", "GOERTZELS2", "quanta", "quantasearch"];
function SaveDefaults()
{
for( i in savedFields )
{
let f = savedFields[i];
let e = document.getElementById(f);
if( e )
{
localStorage.setItem( f, e.value );
}
}
}
function LoadDefaults()
{
for( i in savedFields )
{
let f = savedFields[i];
let e = document.getElementById(f);
if( e && localStorage.getItem( f ) )
{
e.value = localStorage.getItem( f );
}
}
}
function onLoad() function onLoad()
{ {
LoadDefaults();
onLoadWebHidControl(); onLoadWebHidControl();
} }
</SCRIPT> </SCRIPT>
@@ -406,7 +440,7 @@ function onLoad()
<TR> <TR>
<TD VALIGN=TOP> <TD VALIGN=TOP>
<TABLE WIDTH=480> <TABLE WIDTH=480>
<TR><TD>Crystal MHz</TD><TD><INPUT ID=crystalmhz VALUE=144></TD></TR> <TR><TD>System Rate MHz</TD><TD><INPUT ID=crystalmhz VALUE=288></TD></TR>
<TR><TD>Target MHz</TD><TD><INPUT ID=targetmhz VALUE=27.019360></TD></TR> <TR><TD>Target MHz</TD><TD><INPUT ID=targetmhz VALUE=27.019360></TD></TR>
<TR><TD>Quanta</TD><TD><INPUT ID=quanta VALUE=1024> (Goertzel's Only)</TD></TR> <TR><TD>Quanta</TD><TD><INPUT ID=quanta VALUE=1024> (Goertzel's Only)</TD></TR>
<TR><TD>Quanta Search Range</TD><TD><INPUT ID=quantasearch VALUE=64> (Goertzel's Only)</TD></TR> <TR><TD>Quanta Search Range</TD><TD><INPUT ID=quantasearch VALUE=64> (Goertzel's Only)</TD></TR>
+10 -7
View File
@@ -57,6 +57,7 @@ async function closeDeviceTool()
{ {
loopAbort = false; loopAbort = false;
setStatusError( "Disconnected" ); setStatusError( "Disconnected" );
dev = null;
} }
var playingAudioProcessor = null; var playingAudioProcessor = null;
@@ -109,7 +110,7 @@ async function toggleAudio()
if( n == this.rbuffertail ) \ if( n == this.rbuffertail ) \
{ \ { \
this.rbuffertail = (this.rbuffertail + (1|0))%(8192|0); \ this.rbuffertail = (this.rbuffertail + (1|0))%(8192|0); \
console.log( `Overflow` ); \ /*console.log( `Overflow` ); */ \
} \ } \
var vv = e.data[i]; \ var vv = e.data[i]; \
this.dcoffset = this.dcoffset * 0.995 + vv * 0.005; \ this.dcoffset = this.dcoffset * 0.995 + vv * 0.005; \
@@ -127,7 +128,7 @@ async function toggleAudio()
var s = Math.fround( this.sampleplace ); /*float*/ \ var s = Math.fround( this.sampleplace ); /*float*/ \
var tail = this.rbuffertail | 0; /* int*/ \ var tail = this.rbuffertail | 0; /* int*/ \
var tailnext = this.rbuffertail | 0; /* int*/ \ var tailnext = this.rbuffertail | 0; /* int*/ \
if( tail == this.rbufferhead ) { console.log( "Underflow " ); return true; }\ if( tail == this.rbufferhead ) { /*console.log( "Underflow " );*/ return true; }\
var tsamp = Math.fround( this.rbuffer[tail] ); \ var tsamp = Math.fround( this.rbuffer[tail] ); \
var nsamp = Math.fround( this.rbuffer[tailnext] ); \ var nsamp = Math.fround( this.rbuffer[tailnext] ); \
this.totalsampcount += len|0; \ this.totalsampcount += len|0; \
@@ -139,7 +140,7 @@ async function toggleAudio()
s -= excess; \ s -= excess; \
tail = ( tail + (excess|0) ) % (8192|0); \ tail = ( tail + (excess|0) ) % (8192|0); \
tailnext = ( tail + (1|0) ) % (8192|0); \ tailnext = ( tail + (1|0) ) % (8192|0); \
if( tail == this.rbufferhead ) { console.log( "Underflow" ); break; } \ if( tail == this.rbufferhead ) { /* console.log( "Underflow" ); */ break; } \
tsamp = Math.fround( this.rbuffer[tail] ); \ tsamp = Math.fround( this.rbuffer[tail] ); \
nsamp = Math.fround( this.rbuffer[tailnext] ); \ nsamp = Math.fround( this.rbuffer[tailnext] ); \
} \ } \
@@ -186,7 +187,7 @@ async function toggleAudio()
gainParam.setValueAtTime( 0, audioContext.currentTime ); gainParam.setValueAtTime( 0, audioContext.currentTime );
} }
var newVal = 0.1 - targetGain; var newVal = 0.5 - targetGain;
console.log( "Setting gain to: " + newVal ); console.log( "Setting gain to: " + newVal );
let gainParam = playingAudioProcessor.parameters.get("gain"); let gainParam = playingAudioProcessor.parameters.get("gain");
gainParam.setValueAtTime( newVal, audioContext.currentTime); gainParam.setValueAtTime( newVal, audioContext.currentTime);
@@ -267,6 +268,7 @@ let receiveReport = null;
async function sendLoopError( e ) async function sendLoopError( e )
{ {
console.log( "SEND LOOP ERROR" );
sendReport = null; sendReport = null;
receiveReport = null; receiveReport = null;
if( dev ) await dev.close(); if( dev ) await dev.close();
@@ -308,7 +310,7 @@ async function sendLoop()
while( true ) while( true )
{ {
if( dev && !loopAbort ) if( dev && dev !== null && !loopAbort )
{ {
receiveReport = dev.receiveFeatureReport( 0xAD ).catch( sendLoopError ); receiveReport = dev.receiveFeatureReport( 0xAD ).catch( sendLoopError );
if( !receiveReport ) sendLoopError( "error creating receiveReport" ); if( !receiveReport ) sendLoopError( "error creating receiveReport" );
@@ -354,7 +356,7 @@ async function sendLoop()
ctx.fillStyle = `rgb( 255 255 255 )`; ctx.fillStyle = `rgb( 255 255 255 )`;
let mulcoeff = 10000.0 / lastIntensity; let mulcoeff = 30000.0 / lastIntensity;
var lot = 1.2; var lot = 1.2;
var x = 253; var x = 253;
@@ -452,7 +454,7 @@ async function sendLoop()
if( audioContext != null && playingAudioProcessor != null ) if( audioContext != null && playingAudioProcessor != null )
{ {
// TODO: Use crystalmhz // TODO: Use crystalmhz
let sampleAdvance = (144000000.0/sample_divisor) / audioContext.sampleRate; let sampleAdvance = (system_rate/sample_divisor) / audioContext.sampleRate;
let sampleAdvanceParam = playingAudioProcessor.parameters.get("sampleAdvance"); let sampleAdvanceParam = playingAudioProcessor.parameters.get("sampleAdvance");
sampleAdvanceParam.setValueAtTime( sampleAdvance, audioContext.currentTime); sampleAdvanceParam.setValueAtTime( sampleAdvance, audioContext.currentTime);
playingAudioProcessor.port.postMessage( demodbuffer ); playingAudioProcessor.port.postMessage( demodbuffer );
@@ -494,5 +496,6 @@ async function sendLoop()
} }
} }
} }
console.log( "ABORT\n" );
} }
+4 -6
View File
@@ -223,7 +223,6 @@ blocks:
alias: '' alias: ''
comment: '' comment: ''
en_uvec: 'True' en_uvec: 'True'
log_level: info
states: states:
bus_sink: false bus_sink: false
bus_source: false bus_source: false
@@ -467,7 +466,7 @@ blocks:
ant8: '' ant8: ''
ant9: '' ant9: ''
args: '"airspy=0"' args: '"airspy=0"'
bb_gain0: '10' bb_gain0: '25'
bb_gain1: '20' bb_gain1: '20'
bb_gain10: '20' bb_gain10: '20'
bb_gain11: '20' bb_gain11: '20'
@@ -604,7 +603,7 @@ blocks:
dc_offset_mode7: '0' dc_offset_mode7: '0'
dc_offset_mode8: '0' dc_offset_mode8: '0'
dc_offset_mode9: '0' dc_offset_mode9: '0'
freq0: '1090000000' freq0: '100000000'
freq1: 100e6 freq1: 100e6
freq10: 100e6 freq10: 100e6
freq11: 100e6 freq11: 100e6
@@ -636,7 +635,7 @@ blocks:
freq7: 100e6 freq7: 100e6
freq8: 100e6 freq8: 100e6
freq9: 100e6 freq9: 100e6
gain0: '10' gain0: '25'
gain1: '10' gain1: '10'
gain10: '10' gain10: '10'
gain11: '10' gain11: '10'
@@ -700,7 +699,7 @@ blocks:
gain_mode7: 'False' gain_mode7: 'False'
gain_mode8: 'False' gain_mode8: 'False'
gain_mode9: 'False' gain_mode9: 'False'
if_gain0: '10' if_gain0: '25'
if_gain1: '20' if_gain1: '20'
if_gain10: '20' if_gain10: '20'
if_gain11: '20' if_gain11: '20'
@@ -1282,4 +1281,3 @@ connections:
metadata: metadata:
file_format: 1 file_format: 1
grc_version: 3.10.7.0