gbngfdbjn
This commit is contained in:
parent
ec293656e2
commit
2ffe83f951
109
main.c
109
main.c
|
@ -6,43 +6,100 @@
|
|||
#include <stdbool.h>
|
||||
#include <avr/interrupt.h>
|
||||
|
||||
volatile int debounce_int2 = 10;
|
||||
volatile int debounce_int3 = 10;
|
||||
volatile uint16_t tick_timer_start = 0xffff - (F_CPU / 1024 / 1000);
|
||||
volatile bool speaker_disabled = true;
|
||||
|
||||
ISR(INT2_vect) {
|
||||
if (debounce_int2) return;
|
||||
debounce_int2 = 100;
|
||||
OCR0A++;
|
||||
uint16_t notes[][3] = {
|
||||
{ 1000, 200, 30 },
|
||||
{ 1200, 200, 30 },
|
||||
{ 1500, 200, 30 },
|
||||
{ 1600, 200, 30 },
|
||||
{ 1500, 200, 30 },
|
||||
{ 1200, 100, 10 },
|
||||
{ 1000, 300, 100 },
|
||||
};
|
||||
|
||||
void ADC_Setup() {
|
||||
// AVCC with external capacitor at AREF pin
|
||||
ADMUX = _BV(REFS0);
|
||||
|
||||
// Enable ADC, set prescaler to 8tick_timer_start
|
||||
ADCSRA = _BV(ADEN) | _BV(ADPS0) | _BV(ADPS1);
|
||||
|
||||
// Perform dummy readout
|
||||
ADCSRA |= _BV(ADSC); // Start conversion
|
||||
while (ADCSRA & _BV(ADSC)); // Await result
|
||||
(void) ADCW; // Read out result
|
||||
}
|
||||
|
||||
ISR(INT3_vect) {
|
||||
if (debounce_int3) return;
|
||||
debounce_int3 = 100;
|
||||
OCR0A--;
|
||||
uint16_t ADC_Read(uint8_t channel) {
|
||||
// Select chosen channel
|
||||
ADMUX = (ADMUX & ~(0x1F)) | (channel & 0x1F);
|
||||
// Start conversion
|
||||
ADCSRA |= _BV(ADSC);
|
||||
// Await the result
|
||||
while (ADCSRA & _BV(ADSC));
|
||||
// Although it doesn't appear to be documented, ADCW holds the covnersion result
|
||||
return ADCW;
|
||||
}
|
||||
|
||||
ISR(TIMER0_COMPA_vect) {
|
||||
PORTF ^= 0b00000001;
|
||||
uint16_t ADC_Read_Avg(uint8_t channel, uint8_t samples) {
|
||||
uint32_t sum = 0;
|
||||
for (int i = 0; i < samples; i++) {
|
||||
sum += ADC_Read(channel);
|
||||
}
|
||||
return (uint16_t)(sum / samples);
|
||||
}
|
||||
|
||||
void TIMER_Setup() {
|
||||
TCCR1B |= _BV(CS10) | _BV(CS12); // clk/1024
|
||||
|
||||
// Set the TOIE (Timer Overflow Interrupt Enable) bit
|
||||
// on TIMSK1 (Timer 1 Interrupt Mask Register).
|
||||
TIMSK1 |= _BV(TOIE1);
|
||||
|
||||
// Sets the current timer value
|
||||
TCNT1 = tick_timer_start;
|
||||
|
||||
// Enable interrupts
|
||||
sei();
|
||||
}
|
||||
|
||||
// ISR is used to handle interrupts. TIMER1_OVF_vect
|
||||
// is triggered whenever timer 1 (16 bit) overflows.
|
||||
ISR(TIMER1_OVF_vect) {
|
||||
TCNT1 = tick_timer_start;
|
||||
PORTB ^= 0b10000000;
|
||||
|
||||
if (speaker_disabled) PORTK &= 0b11111110;
|
||||
else PORTK ^= 0b00000001;
|
||||
}
|
||||
|
||||
void play_note(uint16_t freq, uint8_t delay, uint8_t delay_silence) {
|
||||
speaker_disabled = false;
|
||||
tick_timer_start = 0xffff - (F_CPU / freq / 1000);
|
||||
for (int i = 0; i < delay; i++) _delay_ms(1);
|
||||
speaker_disabled = true;
|
||||
for (int i = 0; i < delay_silence; i++) _delay_ms(1);
|
||||
}
|
||||
|
||||
void main() {
|
||||
DDRF = 0b00000001;
|
||||
DDRD = 0b00000000;
|
||||
PORTD |= 0b00001100;
|
||||
DDRK = 0b00000001;
|
||||
PORTB = 0b10000000; // Start with LED enabled
|
||||
|
||||
// EIMSK controls which ports can trigger interrupts
|
||||
EIMSK |= _BV(INT2) | _BV(INT3);
|
||||
// Trigger on falling edge on INT2 and INT3
|
||||
EICRA |= _BV(ISC21) | _BV(ISC31);
|
||||
ADC_Setup();
|
||||
TIMER_Setup();
|
||||
|
||||
TCCR0B |= _BV(CS00) | _BV(CS02); // clk/1024
|
||||
TIMSK0 |= _BV(OCIE0A);
|
||||
OCR0A = 0;
|
||||
long rows = sizeof(notes) / sizeof(notes[0]);
|
||||
|
||||
sei();
|
||||
while (true) {
|
||||
for (int i = 0; i < rows; i++) {
|
||||
play_note(notes[i][0], notes[i][1], notes[i][2]);
|
||||
}
|
||||
|
||||
while(1) {
|
||||
_delay_ms(10);
|
||||
OCR0A++;
|
||||
//uint16_t value = ADC_Read_Avg(0, 4);
|
||||
//speaker_disabled = value == 0;
|
||||
//if (value < 100) value = 100; // Anything lower than this causes issues
|
||||
//tick_timer_start = 0xffff - (F_CPU / value / 1000);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue