mirror of
https://github.com/cnlohr/lolra.git
synced 2026-06-21 18:29:28 +00:00
Compare commits
4 Commits
529e85e066
...
933a3d4347
| Author | SHA1 | Date | |
|---|---|---|---|
| 933a3d4347 | |||
| 4c84e5e538 | |||
| 01216baaf9 | |||
| 9044689537 |
+1
-1
Submodule ch32v/ch32v003fun updated: b987542621...7b3d90e829
@@ -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,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
**/
|
||||
|
||||
// NOT LORA!!! -- but experimenting with the possibility of rx.
|
||||
|
||||
// SETUP INSTRUCTIONS:
|
||||
// (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) or, for 24.387096762MHz - ../ch32v003fun/minichlink/minichlink -X ECLK 1:150:49:8:3
|
||||
|
||||
/* More notes
|
||||
|
||||
* Minimum sample time with DMA = fCPU / 28 (5.14MHz)
|
||||
|
||||
*/
|
||||
|
||||
// TODO:
|
||||
// 1: Cleanup some code.
|
||||
// 2: Leverage other ADC.
|
||||
// 3:
|
||||
|
||||
|
||||
#include "ch32v003fun.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.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 SSD1306_REMAP_I2C
|
||||
//#define PWM_OUTPUT
|
||||
#define ENABLE_OLED
|
||||
#define PROFILING_PIN PA0
|
||||
|
||||
//#define SSD1306_I2C_IRQ
|
||||
#include "ssd1306_i2c.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 "../ch32v003fun/examples_v20x/otg_device/otgusb.h"
|
||||
|
||||
@@ -79,78 +109,22 @@ SOFTWARE.
|
||||
|
||||
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_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
|
||||
int g_pwm_period = (30-1);
|
||||
int g_goertzel_buffer = (180);
|
||||
int g_exactcompute = (0);
|
||||
int32_t g_goertzel_omega_per_sample = 5509657063; // 0.816667 of whole per step / 0.880000MHz
|
||||
// Very basic setup, for tuning to 880AM
|
||||
int g_pwm_period = (60-1);
|
||||
int g_exactcompute = (1);
|
||||
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_s = -1961823932;
|
||||
int32_t g_goertzel_coefficient_s = 1961823932;
|
||||
int32_t g_goertzel_advance_r = -3425;
|
||||
int32_t g_goertzel_advance_i = 32588;
|
||||
#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;
|
||||
|
||||
#define LOG_GOERTZEL_LIST 512
|
||||
@@ -162,49 +136,59 @@ void SetupADC()
|
||||
// XXX TODO -look into PGA
|
||||
// XXX TODO - Look into tag-teaming the ADCs
|
||||
|
||||
// PDA is analog input chl 7
|
||||
GPIOA->CFGLR &= ~(0xf<<(4*7)); // CNF = 00: Analog, MODE = 00: Input
|
||||
// PDA is analog input chl CHANNEL
|
||||
GPIOA->CFGLR &= ~(0xf<<(4*CHANNEL)); // CNF = 00: Analog, MODE = 00: Input
|
||||
|
||||
// ADC CLK is chained off of APB2.
|
||||
|
||||
// Reset the ADC to init all regs
|
||||
RCC->APB2PRSTR |= RCC_APB2Periph_ADC1;
|
||||
RCC->APB2PRSTR &= ~RCC_APB2Periph_ADC1;
|
||||
RCC->APB2PRSTR |= RCC_APB2Periph_ADC1 | RCC_APB2Periph_ADC2;
|
||||
RCC->APB2PRSTR &= ~( RCC_APB2Periph_ADC1 | RCC_APB2Periph_ADC2 );
|
||||
|
||||
// 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_DIV2; // Fastest possible (divide-by-2) NOTE: This is OUTSIDE the specified value in the datasheet.
|
||||
|
||||
// Set up single conversion on chl 7
|
||||
ADC1->RSQR1 = 0;
|
||||
ADC1->RSQR2 = 0;
|
||||
ADC1->RSQR3 = 7; // 0-9 for 8 ext inputs and two internals
|
||||
ADC1->RSQR3 = CHANNEL; // 0-9 for 8 ext inputs and two internals Set to 7 for PA7
|
||||
ADC2->RSQR3 = CHANNEL; // 0-9 for 8 ext inputs and two internals Set to 7 for PA7
|
||||
|
||||
ADC1->ISQR = CHANNEL; // Mirror in case we switch to injection mode.
|
||||
ADC2->ISQR = CHANNEL;
|
||||
|
||||
// Not using injection group.
|
||||
|
||||
// Sampling time for channels. Careful: This has PID tuning implications.
|
||||
// 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
|
||||
// 0 = Use TRGO event for Timer 1 to fire ADC rule.
|
||||
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
|
||||
ADC1->CTLR2 |= ADC_RSTCAL;
|
||||
ADC2->CTLR2 |= ADC_RSTCAL;
|
||||
while(ADC1->CTLR2 & ADC_RSTCAL);
|
||||
while(ADC2->CTLR2 & ADC_RSTCAL);
|
||||
|
||||
// Calibrate ADC
|
||||
ADC1->CTLR2 |= ADC_CAL;
|
||||
ADC2->CTLR2 |= ADC_CAL;
|
||||
while(ADC1->CTLR2 & ADC_CAL);
|
||||
while(ADC2->CTLR2 & ADC_CAL);
|
||||
|
||||
// ADC_SCAN: Allow scanning.
|
||||
ADC2->CTLR1 = ADC_SCAN;
|
||||
ADC1->CTLR1 =
|
||||
//ADC_SCAN;
|
||||
ADC_SCAN | ADC_BUFEN ;
|
||||
//ADC_Pga_16 | ADC_SCAN | ADC_BUFEN ;
|
||||
//ADC_Pga_64 | ADC_SCAN;
|
||||
|
||||
//ADC_DUALMOD_0 | ADC_DUALMOD_3 | // Alternate Trigger Mode (Can't use with DMA)
|
||||
ADC_SCAN;
|
||||
//ADC_Pga_16 | ADC_BUFEN ;
|
||||
//ADC_Pga_64 | ADC_BUFEN;
|
||||
|
||||
// Turn on DMA
|
||||
RCC->AHBPCENR |= RCC_AHBPeriph_DMA1;
|
||||
@@ -212,32 +196,21 @@ void SetupADC()
|
||||
//DMA1_Channel1 is for ADC
|
||||
DMA1_Channel1->PADDR = (uint32_t)&ADC1->RDATAR;
|
||||
DMA1_Channel1->MADDR = (uint32_t)adc_buffer;
|
||||
DMA1_Channel1->CNTR = ADC_BUFFSIZE;
|
||||
DMA1_Channel1->CNTR = ADC_BUFFSIZE/2;
|
||||
DMA1_Channel1->CFGR =
|
||||
DMA_M2M_Disable |
|
||||
DMA_Priority_VeryHigh |
|
||||
DMA_MemoryDataSize_HalfWord |
|
||||
DMA_PeripheralDataSize_HalfWord |
|
||||
DMA_MemoryDataSize_Word |
|
||||
DMA_PeripheralDataSize_Word |
|
||||
DMA_MemoryInc_Enable |
|
||||
DMA_Mode_Circular |
|
||||
DMA_DIR_PeripheralSRC;
|
||||
|
||||
// NVIC_SetPriority( DMA1_Channel1_IRQn, 0<<4 ); //We don't need to tweak priority.
|
||||
NVIC_EnableIRQ( DMA1_Channel1_IRQn );
|
||||
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
|
||||
ADC1->CTLR2 |= ADC_DMA; // | ADC_CONT;
|
||||
|
||||
// start conversion
|
||||
ADC1->CTLR2 |= ADC_SWSTART;// | ADC_CONT;
|
||||
|
||||
}
|
||||
|
||||
static void SetupTimer1()
|
||||
@@ -261,18 +234,80 @@ static void SetupTimer1()
|
||||
TIM1->BDTR |= 0xc000;//TIM_MOE;
|
||||
#endif
|
||||
|
||||
TIM1->CCER |= TIM_CC1E;
|
||||
TIM1->CCER |= TIM_CC1E | TIM_CC4E | TIM_CC3E;
|
||||
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)
|
||||
//TIM1->CTLR2 = TIM_MMS_1;
|
||||
// Setup TRGO to trigger for ADC injection group
|
||||
TIM1->CTLR2 = TIM_MMS_1;
|
||||
|
||||
// Enable TIM1 outputs
|
||||
TIM1->BDTR = TIM_MOE;
|
||||
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));
|
||||
|
||||
@@ -319,7 +354,9 @@ void DMA1_Channel1_IRQHandler( void )
|
||||
// Clear all possible flags.
|
||||
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 = (tpl & (ADC_BUFFSIZE-1));
|
||||
if( tpl == ADC_BUFFSIZE ) tpl = 0;
|
||||
@@ -338,6 +375,9 @@ void DMA1_Channel1_IRQHandler( void )
|
||||
// Here is where the magic happens.
|
||||
|
||||
#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 GOERTZELLOOP(idx) \
|
||||
asm volatile("\n\
|
||||
@@ -421,8 +461,9 @@ void DMA1_Channel1_IRQHandler( void )
|
||||
}
|
||||
|
||||
// Now, rotate rr, ri by that phasor.
|
||||
temp = (g_goertzel_phasor_r * ri + g_goertzel_phasor_i * rr) >> 15;
|
||||
rr = (g_goertzel_phasor_r * rr - g_goertzel_phasor_i * ri) >> 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.
|
||||
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;
|
||||
|
||||
// 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_head = ( qibaselogs_head + 1 ) & ((LOG_GOERTZEL_LIST)-1);
|
||||
|
||||
rr>>=2;
|
||||
ri>>=2;
|
||||
|
||||
int s = rr * rr + ri * ri;
|
||||
//int intensity = 1<<( ( 32 - __builtin_clz(s) )/2);
|
||||
#define ABS(x) (((x)<0)?-(x):(x))
|
||||
@@ -442,6 +480,10 @@ void DMA1_Channel1_IRQHandler( void )
|
||||
intensity++;
|
||||
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);
|
||||
|
||||
#ifdef PWM_OUTPUT
|
||||
@@ -460,6 +502,18 @@ void DMA1_Channel1_IRQHandler( void )
|
||||
adc_offset -= accumulate_over_window / g_goertzel_buffer;
|
||||
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
|
||||
funDigitalWrite( PROFILING_PIN, 1 );
|
||||
#endif
|
||||
@@ -492,7 +546,6 @@ static inline uint32_t gets2()
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void InnerLoop()
|
||||
{
|
||||
while(1){
|
||||
@@ -507,13 +560,12 @@ void InnerLoop()
|
||||
}
|
||||
#endif
|
||||
|
||||
int pxa = 0;
|
||||
|
||||
// Only display half of the list so the other half could
|
||||
// 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++ )
|
||||
{
|
||||
@@ -534,12 +586,8 @@ void InnerLoop()
|
||||
if( rr > 127 ) rr = 127;
|
||||
if( ri > 127 ) ri = 127;
|
||||
|
||||
#ifdef ENABLE_OLED
|
||||
ssd1306_drawPixel( rr, ri, 1 );
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef ENABLE_OLED
|
||||
//char cts[32];
|
||||
//snprintf( cts, 32, "%d", intensity_average );
|
||||
//ssd1306_drawstr( 0, 0, cts, 1 );
|
||||
@@ -550,20 +598,43 @@ void InnerLoop()
|
||||
//if( ik == sizeof(ssd1306_buffer) ) ik = 0;
|
||||
|
||||
ssd1306_setbuf(0);
|
||||
|
||||
#else
|
||||
Delay_Ms(17);
|
||||
#endif
|
||||
|
||||
// printf( "%6d %8d %8d - %8d %8d - %8d\n", g_goertzel_outs,g_goertzelp2_store, g_goertzelp_store, rr, ri, x );
|
||||
|
||||
// Delay_Ms(940);
|
||||
//printf( "!!!!\n ");
|
||||
|
||||
// Do nothing.
|
||||
Delay_Ms(17);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
SystemInit();
|
||||
@@ -604,7 +675,7 @@ int main()
|
||||
|
||||
SetupADC();
|
||||
|
||||
#ifdef ENABLE_OLED
|
||||
#if defined( ENABLE_OLED )
|
||||
ssd1306_i2c_setup();
|
||||
ssd1306_i2c_init();
|
||||
|
||||
@@ -617,32 +688,49 @@ int main()
|
||||
ssd1306_refresh();
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
int i = 0;
|
||||
int k = 0;
|
||||
int frame = 0;
|
||||
while( 1)
|
||||
{
|
||||
// ssd1306_drawLine( (frame)%128, (0)%128, (0)%128, (127-frame)%128, 1 );
|
||||
ssd1306_drawstr( frame%128, frame%128, "hello", 1 );
|
||||
#ifdef ENABLE_OLED_SCOPE
|
||||
int i;
|
||||
|
||||
ssd1306_refresh();
|
||||
ssd1306_setbuf(0);
|
||||
frame++;
|
||||
ssd1306_spi_init();
|
||||
ssd1306_rst();
|
||||
|
||||
if( ssd1306_init() )
|
||||
printf( "Failed to initialize OLED\n" );
|
||||
else
|
||||
printf( "Initialized OLED\n" );
|
||||
|
||||
ssd1306_setbuf(0);
|
||||
|
||||
// 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
|
||||
|
||||
#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
|
||||
|
||||
#ifdef PROFILING_PIN
|
||||
@@ -743,7 +831,7 @@ void HandleHidUserReportOutComplete( struct _USBState * ctx )
|
||||
uint32_t * configs = (uint32_t*)scratchpad;
|
||||
// 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];
|
||||
if( numconfigs > 0) g_pwm_period = configs[2];
|
||||
@@ -762,13 +850,13 @@ void HandleHidUserReportOutComplete( struct _USBState * ctx )
|
||||
// Consider using PGA.
|
||||
//ADC_Pga_16 | ADC_SCAN | ADC_BUFEN ;
|
||||
//ADC_Pga_64 | ADC_SCAN;
|
||||
ADC1->CTLR1 =
|
||||
ADC_SCAN | ADC_BUFEN;
|
||||
ADC1->CTLR1 |= ADC_BUFEN;// | ADC_Pga_4; // Adding PGA causes wild oscillation.
|
||||
ADC1->CTLR2 |= ADC_BUFEN;// | ADC_Pga_4;
|
||||
}
|
||||
else
|
||||
{
|
||||
ADC1->CTLR1 =
|
||||
ADC_SCAN;
|
||||
ADC1->CTLR1 &= (~ADC_BUFEN);
|
||||
ADC2->CTLR1 &= (~ADC_BUFEN);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -776,6 +864,10 @@ void HandleHidUserReportOutComplete( struct _USBState * ctx )
|
||||
g_goertzel_samples = 0;
|
||||
TIM1->ATRLR = g_pwm_period;
|
||||
|
||||
TIM1->CH1CVR = 1;
|
||||
TIM1->CH3CVR = TIM1->ATRLR/2+1;
|
||||
|
||||
|
||||
g_isConfigurePacket = 0;
|
||||
}
|
||||
return;
|
||||
|
||||
@@ -22,6 +22,7 @@ function DrawSpan( rowspan, colspan, freq, target, docolor, extrastr = "" )
|
||||
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 lastGmhz;
|
||||
var lastGfr;
|
||||
@@ -62,7 +63,7 @@ function SendGoertz()
|
||||
|
||||
var g_exactcompute = exact_compute;
|
||||
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_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" +
|
||||
@@ -95,7 +96,8 @@ function SendGoertz()
|
||||
for( var i = 0|0; i < 10; i++ )
|
||||
{
|
||||
var tc = (tz / 1000000000.0) % 10;
|
||||
document.getElementById( "mhzm" + i ).value = tc|0;
|
||||
if( document.getElementById( "mhzm" + i ) )
|
||||
document.getElementById( "mhzm" + i ).value = tc|0;
|
||||
tz *= 10;
|
||||
}
|
||||
}
|
||||
@@ -131,6 +133,8 @@ function mhzm( event, ths )
|
||||
let goertzel2 = document.getElementById("GOERTZEL2").checked;
|
||||
let quanta = Math.round(Number(document.getElementById("quanta").value));
|
||||
let quantasearch = Math.round(Number(document.getElementById("quantasearch").value));
|
||||
SaveDefaults();
|
||||
system_rate = xtal *1000000;
|
||||
|
||||
let n = lastGn;
|
||||
let freq = ( xtal / n );
|
||||
@@ -167,7 +171,7 @@ function computeTable()
|
||||
let goertzel2 = document.getElementById("GOERTZEL2").checked;
|
||||
let quanta = Math.round(Number(document.getElementById("quanta").value));
|
||||
let quantasearch = Math.round(Number(document.getElementById("quantasearch").value));
|
||||
|
||||
SaveDefaults();
|
||||
|
||||
const max_harmonics = 28|0;
|
||||
const min_harmonics = (quadrature?1:0)|0;
|
||||
@@ -206,6 +210,7 @@ function computeTable()
|
||||
|
||||
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 += '<TR><TH>d\\h</div></TH>';
|
||||
for( let h = 0|min_harmonics; h <= max_harmonics; h++ )
|
||||
@@ -279,7 +284,7 @@ function computeTable()
|
||||
if( mode == 0 )
|
||||
{
|
||||
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>";
|
||||
}
|
||||
else if( mode == 1 )
|
||||
@@ -289,7 +294,7 @@ function computeTable()
|
||||
else if( mode == 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>";
|
||||
}
|
||||
else if( mode == 3 )
|
||||
@@ -328,7 +333,7 @@ function computeTable()
|
||||
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 goertzelpoint = 0;
|
||||
@@ -358,7 +363,7 @@ function computeTable()
|
||||
if( rid == 0 )
|
||||
{
|
||||
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>"
|
||||
}
|
||||
}
|
||||
@@ -386,8 +391,37 @@ function computeTable()
|
||||
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()
|
||||
{
|
||||
LoadDefaults();
|
||||
onLoadWebHidControl();
|
||||
}
|
||||
</SCRIPT>
|
||||
@@ -406,7 +440,7 @@ function onLoad()
|
||||
<TR>
|
||||
<TD VALIGN=TOP>
|
||||
<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>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>
|
||||
|
||||
@@ -57,6 +57,7 @@ async function closeDeviceTool()
|
||||
{
|
||||
loopAbort = false;
|
||||
setStatusError( "Disconnected" );
|
||||
dev = null;
|
||||
}
|
||||
|
||||
var playingAudioProcessor = null;
|
||||
@@ -109,7 +110,7 @@ async function toggleAudio()
|
||||
if( n == this.rbuffertail ) \
|
||||
{ \
|
||||
this.rbuffertail = (this.rbuffertail + (1|0))%(8192|0); \
|
||||
console.log( `Overflow` ); \
|
||||
/*console.log( `Overflow` ); */ \
|
||||
} \
|
||||
var vv = e.data[i]; \
|
||||
this.dcoffset = this.dcoffset * 0.995 + vv * 0.005; \
|
||||
@@ -127,7 +128,7 @@ async function toggleAudio()
|
||||
var s = Math.fround( this.sampleplace ); /*float*/ \
|
||||
var tail = 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 nsamp = Math.fround( this.rbuffer[tailnext] ); \
|
||||
this.totalsampcount += len|0; \
|
||||
@@ -139,7 +140,7 @@ async function toggleAudio()
|
||||
s -= excess; \
|
||||
tail = ( tail + (excess|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] ); \
|
||||
nsamp = Math.fround( this.rbuffer[tailnext] ); \
|
||||
} \
|
||||
@@ -186,7 +187,7 @@ async function toggleAudio()
|
||||
gainParam.setValueAtTime( 0, audioContext.currentTime );
|
||||
}
|
||||
|
||||
var newVal = 0.1 - targetGain;
|
||||
var newVal = 0.5 - targetGain;
|
||||
console.log( "Setting gain to: " + newVal );
|
||||
let gainParam = playingAudioProcessor.parameters.get("gain");
|
||||
gainParam.setValueAtTime( newVal, audioContext.currentTime);
|
||||
@@ -267,6 +268,7 @@ let receiveReport = null;
|
||||
|
||||
async function sendLoopError( e )
|
||||
{
|
||||
console.log( "SEND LOOP ERROR" );
|
||||
sendReport = null;
|
||||
receiveReport = null;
|
||||
if( dev ) await dev.close();
|
||||
@@ -308,7 +310,7 @@ async function sendLoop()
|
||||
|
||||
while( true )
|
||||
{
|
||||
if( dev && !loopAbort )
|
||||
if( dev && dev !== null && !loopAbort )
|
||||
{
|
||||
receiveReport = dev.receiveFeatureReport( 0xAD ).catch( sendLoopError );
|
||||
if( !receiveReport ) sendLoopError( "error creating receiveReport" );
|
||||
@@ -354,7 +356,7 @@ async function sendLoop()
|
||||
|
||||
ctx.fillStyle = `rgb( 255 255 255 )`;
|
||||
|
||||
let mulcoeff = 10000.0 / lastIntensity;
|
||||
let mulcoeff = 30000.0 / lastIntensity;
|
||||
|
||||
var lot = 1.2;
|
||||
var x = 253;
|
||||
@@ -452,7 +454,7 @@ async function sendLoop()
|
||||
if( audioContext != null && playingAudioProcessor != null )
|
||||
{
|
||||
// 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");
|
||||
sampleAdvanceParam.setValueAtTime( sampleAdvance, audioContext.currentTime);
|
||||
playingAudioProcessor.port.postMessage( demodbuffer );
|
||||
@@ -494,5 +496,6 @@ async function sendLoop()
|
||||
}
|
||||
}
|
||||
}
|
||||
console.log( "ABORT\n" );
|
||||
}
|
||||
|
||||
|
||||
@@ -223,7 +223,6 @@ blocks:
|
||||
alias: ''
|
||||
comment: ''
|
||||
en_uvec: 'True'
|
||||
log_level: info
|
||||
states:
|
||||
bus_sink: false
|
||||
bus_source: false
|
||||
@@ -467,7 +466,7 @@ blocks:
|
||||
ant8: ''
|
||||
ant9: ''
|
||||
args: '"airspy=0"'
|
||||
bb_gain0: '10'
|
||||
bb_gain0: '25'
|
||||
bb_gain1: '20'
|
||||
bb_gain10: '20'
|
||||
bb_gain11: '20'
|
||||
@@ -604,7 +603,7 @@ blocks:
|
||||
dc_offset_mode7: '0'
|
||||
dc_offset_mode8: '0'
|
||||
dc_offset_mode9: '0'
|
||||
freq0: '1090000000'
|
||||
freq0: '100000000'
|
||||
freq1: 100e6
|
||||
freq10: 100e6
|
||||
freq11: 100e6
|
||||
@@ -636,7 +635,7 @@ blocks:
|
||||
freq7: 100e6
|
||||
freq8: 100e6
|
||||
freq9: 100e6
|
||||
gain0: '10'
|
||||
gain0: '25'
|
||||
gain1: '10'
|
||||
gain10: '10'
|
||||
gain11: '10'
|
||||
@@ -700,7 +699,7 @@ blocks:
|
||||
gain_mode7: 'False'
|
||||
gain_mode8: 'False'
|
||||
gain_mode9: 'False'
|
||||
if_gain0: '10'
|
||||
if_gain0: '25'
|
||||
if_gain1: '20'
|
||||
if_gain10: '20'
|
||||
if_gain11: '20'
|
||||
@@ -1282,4 +1281,3 @@ connections:
|
||||
|
||||
metadata:
|
||||
file_format: 1
|
||||
grc_version: 3.10.7.0
|
||||
|
||||
Reference in New Issue
Block a user