Programming of built in timer of arduino - timer

I am new to programming in IDE. I am using built-in timer of arduino.I am using TDR method to capture reflection from fault location in cable and for that I am using timer.Timer should start as soon as output is send and stop at reflection. I have a reference code for it but I dont able to understand it, so if anyone know about it , it would be great.
void setup()
{
pinMode(stepPin, OUTPUT);
pinMode(refPin, OUTPUT);
pinMode(shutdownPin, OUTPUT);
TCCR1A = 0;
TCCR1B = (1 << ICNC1); // input capture noise canceller enabled, capture on falling edge
TIMSK1 = 0; // timer 1 interrupts disabled
ACSR = 0; // input capture from ICP1 pin
TCCR2B = (1 << CS20); // change timer 2 PWM frequency to 31.25kHz because we're using pin 11 as a DAC
Serial.begin(19200);
}
struct Step
{
unsigned int time;
unsigned int amplitude;
};
// Take a single measurement, using either a positive or negative edge from the comparator.
// The comparator reference voltage must have been set up and allowed to stablise before calling this.
unsigned int takeMeasurement(bool posEdge)
{
byte reg1b = (posEdge) ? 0 : (1 << ICES1); // input capture noise canceller csdisabled, set up input capture polarity, stop timer
reg1b |= (1 << CS10);
TCCR1B = reg1b;
TCNT1H = 0;
TCNT1L = 0; // clear timer
unsigned int capture = 0;
unsigned long start = micros(); // get the time
cli();
TCNT1H = 0;
TCNT1L = 0; // clear timer
TIFR1 = (1 << ICF1); // clear timer 1 input capture bit
PORTD |= (1 << 4); // set output high
sei();
do
{
if ((TIFR1 & (1 << ICF1)) && capture == 0)
{
byte temp = ICR1L;
capture = (ICR1H << 8) | temp;
}
} while (micros() - start < 100);
PORTD &= ~(1 << 4); // set output low
return capture;
}
size_t findSteps(bool positive, struct Step *results, size_t maxResults)
{
byte amplitude = (positive) ? 5 : 250;
analogWrite(refPin, amplitude);
delay(100); // wait 100ms for the output to stabilise
unsigned int lastReading = 0;
size_t numResults = 0;
unsigned int stepSize = 0; // 0 means not in a step
#ifdef DEBUG
Serial.print((positive) ? "pos " : "neg ");
#endif
for (int i = 0; i < 50; ++i)
{
analogWrite(refPin, amplitude);
delay(10);
unsigned int currentReading = takeMeasurement(positive);
unsigned int currentDiff = currentReading - lastReading; // diff since start of possible step
if (stepSize == 0)
{
// Not currently in a step
if (i != 0 && currentReading != 0 && currentDiff == 0)
{
// Found the start of a possible step
++stepSize;
}
lastReading = currentReading;
}
else
{
if (currentDiff > 2 || i + 1 == 50)
{
// Step has endeed, so record it if it is big enough
if (stepSize >= 2)
{
results->time = lastReading;
results->amplitude = amplitude - 5;
++results;
++numResults;
if (numResults == maxResults) break;
}
stepSize = 0;
lastReading = currentReading;
}
else if (currentDiff == 0)
{
++stepSize;
}
}
#ifdef DEBUG
if (i != 0) Serial.write(',');
Serial.print(currentReading);
#endif
if (positive)
{
amplitude += 5;
}
else
{
amplitude -= 5;
}
}
#ifdef DEBUG
Serial.println();
#endif
return numResults;
}

Related

Is this code for initializing an SD card in SPI mode correct?

I want to initialize an SD card manually from an Arduino Mega 2560 and read its contents.
I've read a lot of manuals explaining how to properly do it, as well as the Arduino SD library code, but I can't get it to work.
uint8_t spi_byte(uint8_t byte) {
SPDR = byte;
asm volatile("nop");
while(!(SPSR & B10000000));
uint8_t response = SPDR;
return response;
}
uint8_t sd_cmd(uint8_t cmd, uint32_t args) {
if(cmd != 0x40) while(spi_byte(0xFF) != 0xFF);
spi_byte(cmd);
int8_t c;
for(c = 3; c >= 0; --c) spi_byte(args >> (c << 3));
uint8_t crc;
if(cmd == 0x40) crc = 0x95;
else if(cmd == 0x48) crc = 0x87;
else crc = 0xFF;
spi_byte(crc);
uint8_t response;
for(c = 16; ((response = spi_byte(0xFF)) & 0x80) && c; --c);
/*if((cmd < 0x51) || (cmd > 0x59))*/ spi_byte(0xFF); //S
return response;
}
void sd_init() {
DDRB &= B11110000;
PORTB |= B0001; //set CS pull-up resistor (just-in-case)
DDRB |= B0001; //set CS to output
PORTB |= B1000; //set MISO pull-up resistor (just-in-case)
SPCR = B01010010; //no interrupt, MSB first, master, mode 0, fosc/64 (250 kHz)
SPSR &= ~1; //clear SPI double speed
DDRB |= B0110; //set SCK and MOSI to output
delayMicroseconds(200000);
uint8_t c;
cli();
for(c = 0; c < 10; ++c) spi_byte(0xFF); //synchronize clock
clb(PORTB, 0); //set CS low
uint8_t response;
uint16_t timeout = 1024;
while((response=sd_cmd(0x40, 0)) != 0x1) { //CMD0: reset card
if((!response) || (response == 0xFF)) error(3); //we don't even have a card
if(!--timeout) error(7); //timed out
}
if(sd_cmd(0x48, 0x1AA) != 1) error(1); //CMD8: make sure we are using SD v2
for(c = 0; c < 4; ++c) spi_byte(0xFF);
do {
sd_cmd(0x77, 0); //CMD55: introduce application-specific command
response = sd_cmd(0x69, 0x40000000); //ACMD41: initialize card
if(!--timeout) error(8); //timed out
} while(response != 0);
sd_cmd(0x7A, 0); //CMD58: read OCR
response = spi_byte(0xFF);
if((response & B11000000) != B11000000) error(2); //make sure we are using SDHC
for(c = 0; c < 3; ++c) spi_byte(0xFF);
stb(PORTB, 0); //set CS high
SPCR = B01010000; //fosc/4 (4 MHz)
SPSR |= 1; //set SPI double speed (8 MHz)
for(c = 0; c < 10; ++c) spi_byte(0xFF); //synchronize clock
sei();
return;
}
void sd_read(uint8_t* buffer, uint32_t block, uint8_t start2, uint8_t size2) {
/*start2 and size2 are in 2 byte units, size2 = 0 means whole block (512 B)*/
cli();
block <<= 9; //S//D
clb(PORTB, 0); //set CS low
uint8_t response;
if((response=sd_cmd(0x51, block))) { //CMD17: read single block
Serial.begin(9600); //D
Serial.println(response, HEX); //D
error(10);
}
while(spi_byte(0xFF) != 0xFE) ; //TODO: timeout error 9
uint8_t b = 0; uint8_t end = 0;
do {
if((b >= start2) && (!end)) {
*(buffer++) = spi_byte(0xFF);
*(buffer++) = spi_byte(0xFF);
--size2;
if(!size2) end = 1;
}
else {
spi_byte(0xFF);
spi_byte(0xFF);
}
++b;
} while(b); //repeat 256 times
spi_byte(0xFF); spi_byte(0xFF); //two more bytes to close
stb(PORTB, 0); //set CS high
spi_byte(0xFF);
sei();
return;
}
Some days it works perfectly, other times it just locks up at initialization time, and finally right now I'm trying to read SD card contents and it just displays 0x55AA forever. I suspect that it is a hardware problem, but I'd like to rule out the possibility that my code might be wrong. Also, I don't know why I have to multiply reading address by 512. Being this an SDHC card, I would expect addresses to be in blocks, right?

AVR programming, displaying wrong value on 7 seg. LED

I am interfacing LM35 with Atmega8. To display digits I use 7 segment LED anode display that I connect to AVR both ends (it handles it without transistors so why not). Strange thing happens:
res value after assigning it from adc is 237 (23.7 degrees). I want to print on my display the first digit (2).
If I leave last line in the while commented out, the display first shows digit 2 correctly but after the first delay it shows 1 instead of 2. Otherwise I get correctly digit 2. Why is this happening?
#ifndef F_CPU
#define F_CPU 1000000UL
#endif // F_CPU
#include <avr/io.h>
#include <util/delay.h>
#define DELAY_IN_MS 500 /* 0.5 sec */
int numbers[] = {
0b01000000,
0b01110011,
0b00100100,
0b00100001,
0b00010011,
0b00001001,
0b00001000,
0b01100011,
0b00000000,
0b00000001,
0b11111111 // off
};
uint8_t digits[3];
void initADC()
{
ADMUX=(1<<REFS1)|(1<<REFS0);
ADCSRA=(1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
}
uint16_t ReadADC(uint8_t ch)
{
//Select ADC Channel ch must be 0-7
ch=ch&0b00000111;
ADMUX|=ch;
//Start Single conversion
ADCSRA|=(1<<ADSC);
//Wait for conversion to complete
while(!(ADCSRA & (1<<ADIF)));
//Clear ADIF by writing one to it
ADCSRA|=(1<<ADIF);
return(ADC);
}
int main()
{
DDRD = 0xFF;
PORTD = 0xFF;
DDRB = 0b00000001;
PORTB = 1;
initADC();
uint16_t adc_value;
uint16_t res;
while(1)
{
adc_value = 0;
for (int i = 0; i < 250; i++)
{
adc_value += ReadADC(0);
}
adc_value=(adc_value/25)/4;
res = adc_value;
for(int j = 2; j >= 0; j--) {
digits[j] = res%10;
res /= 10;
}
uint8_t dig = digits[0];
PORTD = numbers[dig];
_delay_ms(DELAY_IN_MS);
// if following is uncommented there blinks digit two correctly
// if commented there is unblinking digit 1
PORTD = numbers[10]; // display off
}
return 0;
}
The problem was induction.
My circuit had many wires in non-soldering-field. When the display was on, there was a lot of induction going on changing resulting voltage on ADC input/LM35 output.
There is more than one solution.
1) Software: I moved ADC conversion into the interruption function. It turns of the displays, converts value from lm35 and displays digit on proper display. It happens so fast that the eye cant perceive it.
I prefer this one for now, because it makes my circuit simpler.
2) Hardware: adding L/C or R/C filter to adc pin should resolve the issue.
Full code for 1)
#ifndef F_CPU
#define F_CPU 1000000UL
#endif // F_CPU
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#define DELAY_IN_MS 5000 /* ms */
#define NUM_OF_MEASUREMENTS 100
#define NUM_DISPLAYS 3
int numbers[] = {
0b10000001,
0b10011111,
0b10100100,
0b10010100,
0b10011010,
0b11010000,
0b11000000,
0b10011101,
0b10000000,
0b10010000,
0b11111111 // off
};
int display = 0;
uint8_t digits[NUM_DISPLAYS];
volatile uint16_t adc_values[NUM_OF_MEASUREMENTS];
int adc_read_cycle_index = 0;
uint32_t res;
void initADC()
{
ADMUX=(1<<REFS1)|(1<<REFS0);
ADCSRA=(1<<ADEN)|(1<<ADPS2);
}
uint16_t ReadADC(uint8_t ch)
{
//Select ADC Channel ch must be 0-7
ch=ch&0b00000111;
ADMUX|=ch;
//Start Single conversion
ADCSRA|=(1<<ADSC);
//Wait for conversion to complete
while (ADCSRA & (1<<ADSC));
return(ADC);
}
void readDegrees()
{
adc_values[adc_read_cycle_index] = (ReadADC(0)*10)/4;
if(adc_read_cycle_index + 1 == NUM_OF_MEASUREMENTS) {
adc_read_cycle_index = 0;
} else {
adc_read_cycle_index++;
}
}
void fetchTemperatureDigits() {
res = 0;
for(int i = 0; i < NUM_OF_MEASUREMENTS; i++) {
res += adc_values[i];
}
res /= NUM_OF_MEASUREMENTS;
for(int j = 2; j >= 0; j--) {
digits[j] = res%10;
res = res / 10;
}
}
void initTimer0()
{
// Prescaler = FCPU/64
TCCR0|=(1<<CS01);//|(1<<CS00);
//Enable Overflow Interrupt Enable
TIMSK|=(1<<TOIE0);
//Initialize Counter
TCNT0=0;
}
ISR(TIMER0_OVF_vect)
{
// turn off displays
PORTD = numbers[10];
// read ADC and convert to degrees
readDegrees();
// turn on proper anode
PORTB &= 0b11111000;
PORTB |= (1<<display);
// show digit
PORTD = numbers[digits[display]];
// show decimal point for second display (21.5 - second display shows "1.")
if(display == 1) {
PORTD &= 0b01111111;
}
// next display for next interruption
display++;
if(display == NUM_DISPLAYS) {
display = 0;
}
}
int main()
{
initADC();
for(int i = 0; i < NUM_OF_MEASUREMENTS; i++) {
readDegrees();
}
DDRD = 0xFF;
PORTD = 0;
DDRB |= 0b00000111;
PORTB |= 1;
initTimer0();
sei();
while(1) {
fetchTemperatureDigits();
_delay_ms(DELAY_IN_MS);
}
return 0;
}

Custom Delay function using arduino IDE

I'm in a microprocessors class and we're writing our own delay functions that are actually accurate. Our professor gave us, what I assume is, a 4 ms delay function. I don't really understand how to transfer that to a .25 s or a 1 s delay, which are both needed for my homework.
The given function is as follows(Assume _BV() is defined as _BV(x) 1<<(x)):
DDRB |= _BV(1);
TCCR1A |= _BV(COM1A0);
TCNT1 = 0;
OCR1A = 100;
TIFR1 = _BV(OCF1A);
TCCR1B |= _BV(CS10);
while((TIFR1 & _BV(OCF1A)) == 0);
TIFR1 = _BV(OCF1A);
OCR1A = 100 + 64000;
while((TIFR1 & _BV(OCF1A)) == 0);
TCCR1B = 0;
TCCR1A = 0;
I've written the code needed to complete the homework except the two delay functions.
Here is what I have so far:
#include <avr/io.h>
uint8_t numIN;
void setup() {
Serial.begin(9600);
DDRB |= _BV(5);
}
void loop() {
int i;
numIN = 10;
Serial.println("Enter a number between 0 and 9.");
do {
while (Serial.available() > 0)
{
numIN = Serial.read() - '0';
if (numIN < 0 || numIN > 9)
{
Serial.println("Input Error!");
}
}
} while (numIN < 0 || numIN > 9);
Serial.print("You entered ");
Serial.println(numIN);
if (isEven(numIN))
{
for (i = 0; i < 5; i++)
{
PORTB |= _BV(5);
delay(1000); //temporary
//delay_Sec();
PORTB &= ~_BV(5);
delay(1000); //temporary
//delay_Sec();
}
}
else
{
for (i = 0; i < 5; i++)
{
PORTB |= _BV(5);
delay(250); //temporary
//delay_quarterSec();
PORTB &= ~_BV(5);
delay(250); //temporary
//delay_quarterSec();
}
}
}
void delay_quarterSec(void)
{
//need to finish
}
void delay_Sec(void)
{
//need to finish
}
boolean isEven(int num)
{
if (num & _BV(0))
return false;
else
return true;
}
I'm just confused how I take my professor's code and transfer it to what I need to do. Any help is greatly appreciated!
I can give you a quick overview about what the provided code does.
(This is from memory, so don't take my word for it. And you don't mention your controller type. You will have to look up the registers up in detail.)
DDRB |= _BV(1); // set the compare match output pin to output
TCCR1A |= _BV(COM1A0); // enable output compare PIN toggle
TCNT1 = 0; // set counter start value to 0
OCR1A = 100; // set compare match value to 100 (the actual delay)
TIFR1 = _BV(OCF1A); // clear the output compare flag
TCCR1B |= _BV(CS10); // enable the timer by setting the pre-scaler
while((TIFR1 & _BV(OCF1A)) == 0); // wait until the timer counted to 100 (compare flag is set again)
So the actual delay depends on:
the setting of the prescaler
the clock speed of your controller
the value of OCR1A
Example:
If the prescaler is set to 1 and you run at 10MHz you got
t = (1 / (10000000/s)) * 100 = 10us
This should get you started.

Modify ALSA arecord function to output audio levels to Raspberry Pi 3 RGB LED

I currently can use my raspberry pi 3 to redirect USB Audio input to an icecast stream. Currently it works fine in small tests when I pipe arecord from USB audio hw input to avconv (ffmpeg equivalent) on Raspbian Jessie Lite.
Arecord has a built in text vu meter for audio levels when you use the verbose setting.
I think the code is located in the attached function. I'm wondering if it's possible to rewrite this function to output to Raspberry Pi 3 RGB LED - to somehow send the red/yellow/green based on volume levels - using the function's peak variable?
I've include the whole function - and the print function. If it could be done, I think the code could probably replace print_vu_meter(perc, maxperc);
Is it possible to modify arecord to get the Raspi 3 to handle the processing during the pipe? Is there a way to use another thread?
Way out of my league here - just looking for a start, or some ideas to get the idea out of my head or to say it's possible.
peak handler
static void compute_max_peak(u_char *data, size_t count)
{
signed int val, max, perc[2], max_peak[2];
static int run = 0;
size_t ocount = count;
int format_little_endian = snd_pcm_format_little_endian(hwparams.format);
int ichans, c;
if (vumeter == VUMETER_STEREO)
ichans = 2;
else
ichans = 1;
memset(max_peak, 0, sizeof(max_peak));
switch (bits_per_sample) {
case 8: {
signed char *valp = (signed char *)data;
signed char mask = snd_pcm_format_silence(hwparams.format);
c = 0;
while (count-- > 0) {
val = *valp++ ^ mask;
val = abs(val);
if (max_peak[c] < val)
max_peak[c] = val;
if (vumeter == VUMETER_STEREO)
c = !c;
}
break;
}
case 16: {
signed short *valp = (signed short *)data;
signed short mask = snd_pcm_format_silence_16(hwparams.format);
signed short sval;
count /= 2;
c = 0;
while (count-- > 0) {
if (format_little_endian)
sval = __le16_to_cpu(*valp);
else
sval = __be16_to_cpu(*valp);
sval = abs(sval) ^ mask;
if (max_peak[c] < sval)
max_peak[c] = sval;
valp++;
if (vumeter == VUMETER_STEREO)
c = !c;
}
break;
}
case 24: {
unsigned char *valp = data;
signed int mask = snd_pcm_format_silence_32(hwparams.format);
count /= 3;
c = 0;
while (count-- > 0) {
if (format_little_endian) {
val = valp[0] | (valp[1]<<8) | (valp[2]<<16);
} else {
val = (valp[0]<<16) | (valp[1]<<8) | valp[2];
}
/* Correct signed bit in 32-bit value */
if (val & (1<<(bits_per_sample-1))) {
val |= 0xff<<24; /* Negate upper bits too */
}
val = abs(val) ^ mask;
if (max_peak[c] < val)
max_peak[c] = val;
valp += 3;
if (vumeter == VUMETER_STEREO)
c = !c;
}
break;
}
case 32: {
signed int *valp = (signed int *)data;
signed int mask = snd_pcm_format_silence_32(hwparams.format);
count /= 4;
c = 0;
while (count-- > 0) {
if (format_little_endian)
val = __le32_to_cpu(*valp);
else
val = __be32_to_cpu(*valp);
val = abs(val) ^ mask;
if (max_peak[c] < val)
max_peak[c] = val;
valp++;
if (vumeter == VUMETER_STEREO)
c = !c;
}
break;
}
default:
if (run == 0) {
fprintf(stderr, _("Unsupported bit size %d.\n"), (int)bits_per_sample);
run = 1;
}
return;
}
max = 1 << (bits_per_sample-1);
if (max <= 0)
max = 0x7fffffff;
for (c = 0; c < ichans; c++) {
if (bits_per_sample > 16)
perc[c] = max_peak[c] / (max / 100);
else
perc[c] = max_peak[c] * 100 / max;
}
if (interleaved && verbose <= 2) {
static int maxperc[2];
static time_t t=0;
const time_t tt=time(NULL);
if(tt>t) {
t=tt;
maxperc[0] = 0;
maxperc[1] = 0;
}
for (c = 0; c < ichans; c++)
if (perc[c] > maxperc[c])
maxperc[c] = perc[c];
putchar('\r');
print_vu_meter(perc, maxperc);
fflush(stdout);
}
else if(verbose==3) {
printf(_("Max peak (%li samples): 0x%08x "), (long)ocount, max_peak[0]);
for (val = 0; val < 20; val++)
if (val <= perc[0] / 5)
putchar('#');
else
putchar(' ');
printf(" %i%%\n", perc[0]);
fflush(stdout);
}
}
print_vu_meter
static void print_vu_meter_mono(int perc, int maxperc)
{
const int bar_length = 50;
char line[80];
int val;
for (val = 0; val <= perc * bar_length / 100 && val < bar_length; val++)
line[val] = '#';
for (; val <= maxperc * bar_length / 100 && val < bar_length; val++)
line[val] = ' ';
line[val] = '+';
for (++val; val <= bar_length; val++)
line[val] = ' ';
if (maxperc > 99)
sprintf(line + val, "| MAX");
else
sprintf(line + val, "| %02i%%", maxperc);
fputs(line, stdout);
if (perc > 100)
printf(_(" !clip "));
}
Doesn't look like there's much interest in this, but I thought I'd post my answer for future, in case anyone else tries to delve into this type of project.
Findings:
arecord is just a linked copy of aplay
you can use the incredible wiringPi c library to add a thread to the C code
by adding a static volatile int variable to the code - it becomes shared with between thread and main program
setting the variable to the perc value means it's updated immediately in the threaded program
I was able to simulate a 6 level audio level meter with LEDs using this code:
I used a button on the breadboard to toggle between LED levels being displayed and not.
setAudioLEDS threaded function:
PI_THREAD (setAudioLEDs)
{
// Only update LEDS if button is pressed
// Gets Audio Level from global var: globalAudioLevel
// Wiring Pi Constants for led and button
// Pin number declarations. We're using the Broadcom chip pin numbers.
#define CYCLE_UPDATE '0'
#define CYCLE_STEADY '1'
int last_button;
int last_cycle;
int this_cycle;
// Button is released if this returns 1
// HIGH or LOW (1 or 0)
last_button = digitalRead(butPin);
last_cycle = CYCLE_STEADY;
this_cycle = last_cycle;
while (1)
{
if (digitalRead(butPin) != last_button) {
if (last_cycle == CYCLE_UPDATE)
this_cycle = CYCLE_STEADY;
else
this_cycle = CYCLE_UPDATE;
last_cycle = this_cycle;
}
switch (this_cycle) {
case CYCLE_UPDATE:
// Set LEDS based on audio level
if (globalAudioLevel > 20)
digitalWrite(led1, HIGH); // Turn LED ON
else
digitalWrite(led1, LOW); // Turn LED OFF
if (globalAudioLevel > 40)
digitalWrite(led2, HIGH); // Turn LED ON
else
digitalWrite(led2, LOW); // Turn LED OFF
if (globalAudioLevel > 60)
digitalWrite(led3, HIGH); // Turn LED ON
else
digitalWrite(led3, LOW); // Turn LED OFF
if (globalAudioLevel > 70)
digitalWrite(led4, HIGH); // Turn LED ON
else
digitalWrite(led4, LOW); // Turn LED OFF
if (globalAudioLevel > 80)
digitalWrite(led5, HIGH); // Turn LED ON
else
digitalWrite(led5, LOW); // Turn LED OFF
if (globalAudioLevel > 90)
digitalWrite(led6, HIGH); // Turn LED ON
else
digitalWrite(led6, LOW); // Turn LED OFF
break;
default:
/* Button hasn't been pressed */
digitalWrite(led1, LOW); // Turn LED OFF
digitalWrite(led2, LOW); // Turn LED OFF
digitalWrite(led3, LOW); // Turn LED OFF
digitalWrite(led4, LOW); // Turn LED OFF
digitalWrite(led5, LOW); // Turn LED OFF
digitalWrite(led6, LOW); // Turn LED OFF
}
}
}
I have something working as a ALSA scope plugin so any audio played will start my led vu meter. All you have to do is install the plugin and edit /etc/asound.conf to include the plugin.
I found pivumeter (https://github.com/pimoroni/pivumeter) which is based on ameter (http://laugeo.free.fr/ameter.html) and created my own devices for a 2 channel stereo 16 LED using GPIO pins and another that uses two shift registers and SPI.
My fork can be found here: https://github.com/linuxgnuru/pivumeter
To add your own device, you'll need to edit Makefile.am, src/pivumeter.c (at the bottom add your function), src/devices/all.h, and your code in src/devices/YOURDEVICE.c and src/devices/YOURDEVICE.h
I plan on going through the ALSA C library for the scope plugin and making my own plugin from scratch.
https://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m___scope.html

8051 c interrupts

I'm using C to write a program on an 8051 microcontroller. The compiler I'm using is Keil Microvision. I'm stuck and having trouble figuring out what is missing from my code. I know it's very basic code I just can't figure out what I'm supposed to do.
So pretty much what I am doing is taking sending a sentence out to the user and having them answer yes or no through the serial port and I used a serial interrupt. That part works fine. If I get a no from the person I want to generate a square wave 5kHz by a timer interrupt. I want this square wave to be controlled by an external interrupt turning it on and off when the external interrupt on pin P3.2 is either on or off.
Here is all my code
#include <REG52.H>
#include <stdio.h>
sbit WAVE = P1 ^ 7;
#define BIT(x) (1 << (x))
void timer0() interrupt 1 // timer is controlling square wave timer 0
{
WAVE = ~WAVE;
}
void interrupt0() interrupt 0
{
IE ^= BIT(1);
}
void serial0() interrupt 4
{
unsigned char x;
unsigned int i, z;
unsigned char yes[] = " YES ";
unsigned char no[] = " NO ";
unsigned char nvalid[] = " NOT VALID TRY AGAIN ";
while (RI == 1) {
x = SBUF;
RI = 0;
if (z < 1) {
if (x == 'n') {
for (i = 0; i < 4; i++) {
SBUF = no[i];
while (TI == 0) ; //wait for transmit
TI = 0;
z++;
}
}
} else {
return;
}
if (x == 'y') {
for (i = 0; i < 5; i++) {
SBUF = yes[i];
while (TI == 0) ;
TI = 0;
}
} else if (x != 'n') {
for (i = 0; i < 21; i++) {
SBUF = nvalid[i];
while (TI == 0) ;
TI = 0;
}
}
TI = 0;
return;
}
}
void main()
{
TMOD = 0x20;
TH1 = 0xF6; //baud rate
SCON = 0x50;
TH0 = 0xA4;
IE = 0x93; //enable interrupts
IP = 0x10; // propriety to serial interrupt
TR1 = 1; //start timer 1
TR0 = 1; //clear timer 0
TI = 1;
printf("Hello, Are you okay? Press y for yes and n for no ");
while (1) ;
}
The part I'm having trouble with is these two interrupt from the previous code
void timer0() interrupt 1 // timer is controlling square wave timer 0
{
WAVE=~WAVE;
}
void interrupt0() interrupt 0
{
IE ^= BIT(1);
}
Any hints in the right direction would be greatly appreciated! Thanks. Sorry about formatting
Variables that are modified by interrupts should be defined as volatile:
volatile sbit WAVE = P1 ^ 7;

Resources