Interrupt handling (Arduino vs. Stm32dunio)
Posted: Thu Feb 04, 2021 9:03 pm
Hey guys,
I'm coming from pretty much exclusively Arduino territory as far as microprocessors are concerned, but I've run out of power.
I'm trying to port my Arduino code over to the STM32 family. I've got my board (Just an eBay BluePill) uploaded with the HID 2.2 bootloader, and I've been able to do the whole blink test, and some serial communication, but my main aim is to bring over some code for a 12-bit SPI DAC (MCP4921) as I'm messing around with a synthesiser.
I based my Arduino design off of the Critter and Guitari Arduino Piano (https://github.com/critterandguitari/Ar ... e-Sketches), which is basically using some 8-bit wavetable synthesis, and I've been adding more voices and adding some basic ADSR, but I've obviously run out of processing power.
To the problem! I've had a google around and searched the forum, but I couldn't really find an answer... It's probably more than obvious to those of you who are rarely running these boards.
My code (at the bottom of the post) relies on an ISR (on TIMER2 on the Uno) to calculate and send out the DAC code via SPI and is currently using some Port Manipulation to do this. I'm sure I'm going to have to change the port manipulation stuff, but I'll figure that later.
My first hurdle is the ISR code (along with all the definitions/setup for the timer) spits out:
As I'm coming from using Arduino's I'm starting off by using Arduino IDE 1.8.13, on MacOS Mojave (10.14.6) and the stm32duino (STM Cores 1.9.0).
I think I'm going to move to the PlatformIO environment, but one thing at a time.
TLDR; adapting interrupts from Arduino to STM32duino.
Cheers for all the help!
Nick
I'm coming from pretty much exclusively Arduino territory as far as microprocessors are concerned, but I've run out of power.
I'm trying to port my Arduino code over to the STM32 family. I've got my board (Just an eBay BluePill) uploaded with the HID 2.2 bootloader, and I've been able to do the whole blink test, and some serial communication, but my main aim is to bring over some code for a 12-bit SPI DAC (MCP4921) as I'm messing around with a synthesiser.
I based my Arduino design off of the Critter and Guitari Arduino Piano (https://github.com/critterandguitari/Ar ... e-Sketches), which is basically using some 8-bit wavetable synthesis, and I've been adding more voices and adding some basic ADSR, but I've obviously run out of processing power.
To the problem! I've had a google around and searched the forum, but I couldn't really find an answer... It's probably more than obvious to those of you who are rarely running these boards.
My code (at the bottom of the post) relies on an ISR (on TIMER2 on the Uno) to calculate and send out the DAC code via SPI and is currently using some Port Manipulation to do this. I'm sure I'm going to have to change the port manipulation stuff, but I'll figure that later.
My first hurdle is the ISR code (along with all the definitions/setup for the timer) spits out:
I'm pretty sure there's a different call out for the timer stuff, and I tried searching around with some terms, but wasn't quite sure what I was looking for. I'm pretty sure the port manipulation stuff will need rewriting (and maybe even just being brought up to digitalWrites or something else now I have more juice?), and I read some stuff about HAL and the DMA, but I'd like to just ease my way into this whole STM32 thing...error: expected constructor, destructor, or type conversion before '(' token
53 | ISR(TIM2_COMPA_vect) {
As I'm coming from using Arduino's I'm starting off by using Arduino IDE 1.8.13, on MacOS Mojave (10.14.6) and the stm32duino (STM Cores 1.9.0).
I think I'm going to move to the PlatformIO environment, but one thing at a time.
TLDR; adapting interrupts from Arduino to STM32duino.
Cheers for all the help!
Nick
Code: Select all
// Here is the sine wave. It is a one cycle of sine tone, 255 8 bit samples, in hex values
// you could put any wave form you line in here...
uint8_t sineTable[]={
0x80,0x83,0x86,0x89,0x8c,0x8f,0x92,0x95,0x98,0x9c,0x9f,0xa2,0xa5,0xa8,0xab,0xae,
0xb0,0xb3,0xb6,0xb9,0xbc,0xbf,0xc1,0xc4,0xc7,0xc9,0xcc,0xce,0xd1,0xd3,0xd5,0xd8,
0xda,0xdc,0xde,0xe0,0xe2,0xe4,0xe6,0xe8,0xea,0xec,0xed,0xef,0xf0,0xf2,0xf3,0xf5,
0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfc,0xfd,0xfe,0xfe,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xfe,0xfd,0xfc,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,
0xf6,0xf5,0xf3,0xf2,0xf0,0xef,0xed,0xec,0xea,0xe8,0xe6,0xe4,0xe2,0xe0,0xde,0xdc,
0xda,0xd8,0xd5,0xd3,0xd1,0xce,0xcc,0xc9,0xc7,0xc4,0xc1,0xbf,0xbc,0xb9,0xb6,0xb3,
0xb0,0xae,0xab,0xa8,0xa5,0xa2,0x9f,0x9c,0x98,0x95,0x92,0x8f,0x8c,0x89,0x86,0x83,
0x80,0x7c,0x79,0x76,0x73,0x70,0x6d,0x6a,0x67,0x63,0x60,0x5d,0x5a,0x57,0x54,0x51,
0x4f,0x4c,0x49,0x46,0x43,0x40,0x3e,0x3b,0x38,0x36,0x33,0x31,0x2e,0x2c,0x2a,0x27,
0x25,0x23,0x21,0x1f,0x1d,0x1b,0x19,0x17,0x15,0x13,0x12,0x10,0x0f,0x0d,0x0c,0x0a,
0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x03,0x02,0x01,0x01,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x05,0x06,0x07,0x08,
0x09,0x0a,0x0c,0x0d,0x0f,0x10,0x12,0x13,0x15,0x17,0x19,0x1b,0x1d,0x1f,0x21,0x23,
0x25,0x27,0x2a,0x2c,0x2e,0x31,0x33,0x36,0x38,0x3b,0x3e,0x40,0x43,0x46,0x49,0x4c,
0x4f,0x51,0x54,0x57,0x5a,0x5d,0x60,0x63,0x67,0x6a,0x6d,0x70,0x73,0x76,0x79,0x7c};
// final sample that goes tote DAC
uint16_t sample;
// the two bytes that go to the DAC over SPI
uint8_t dacSPI0;
uint8_t dacSPI1;
// variables for oscillators
uint16_t accumulator = 0; // large number holds phase
uint8_t index = 0; // index for wave lookup (the upper 8 bits of the accumulator)
uint16_t oscil = 8; // oscillator output
#define PP_LED 8 // LED on pocket piano
// holds frequency value used for oscillator in phase steps
// this is an integer proportial to Hertz in the following way:
// frequency = (FrequencyInHertz * 65536) / SampleRate, here sample rate is 15625
uint32_t frequency = 0;
uint8_t gain = 0xff; // gain of oscillator
int pitchScale;
void setup(){
//Timer2 setup This is the audio rate timer, fires an interrupt at 15625 Hz sampling rate
TIMSK2 = 1<<OCIE2A; // interrupt enable audio timer
OCR2A = 127;
TCCR2A = 2; // CTC mode, counts up to 127 then resets
TCCR2B = 0<<CS22 | 1<<CS21 | 0<<CS20; // different for atmega8 (no 'B' i think)
SPCR = 0x50; // set up SPI port
SPSR = 0x01;
DDRB |= 0x2E; // PB output for DAC CS, and SPI port
PORTB |= (1<<1);
//led
pinMode(PP_LED, OUTPUT);
Serial.begin(9600);
Serial.println("hello");
Serial.println("welcome to synthesizer");
//
sei(); // global interrupt enable
}
void loop(void)
{
float frequencyInHertz = 440.0; // use this to hold a frequency in hertz
// normally we wouldn't use floats, and just use integers,
// but it is convinient here to show freqency calculation
// using formula above, calculate correct oscillator frequency value
frequency = (frequencyInHertz * 65536.0) / 15625.0;
Serial.println("playing");
}
// timer 2 is audio interrupt timer
ISR(TIM2_COMPA_vect) {
OCR2A = 127;
// calculate frequency mod
accumulator = accumulator + frequency; // add in pith, the higher the number, the faster it rolls over, the more cycles per second
index = accumulator >> 8; // use top 8 bits as wavetable index
oscil = sineTable[index]; // get sample from wave table
sample = oscil << 8; // sample format for DAC is 12 bit, left justified
// format sample for SPI port
dacSPI0 = sample >> 8;
dacSPI0 >>= 4;
dacSPI0 |= 0x30;
dacSPI1 = sample >> 4;
// transmit value out the SPI port
PORTB &= ~(1<<1); // Frame sync low
SPDR = dacSPI0;
while (!(SPSR & (1<<SPIF)));
SPDR = dacSPI1;
while (!(SPSR & (1<<SPIF)));
PORTB |= (1<<1); // Frame sync high
}