#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <avr/eeprom.h>
// Definizioni per la gestione del Rotary Encoder
#define ENCODER_PIN_A PD2
#define ENCODER_PIN_B PD3
#define ENCODER_BUTTON_PIN PD4
// Variabili globali
volatile uint16_t sampling_frequency = 1000; // Frequenza di campionamento predefinita
volatile uint16_t sample_counter = 0;
volatile uint8_t sampling = 0;
volatile uint16_t eeprom_address = 0;
volatile uint16_t max_samples = 1024; // Capacità della EEPROM in numero di campioni
void setup() {
// Configurazione seriale
UBRR0H = 0;
UBRR0L = 103; // Baud rate 9600 bps con F_CPU = 16 MHz
UCSR0B = (1 << TXEN0); // Abilita trasmissione
UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); // Set frame: 8 data bits, 1 stop bit
// Configurazione ADC
ADMUX = (1 << REFS0); // Riferimento AVcc
ADCSRA = (1 << ADEN) | (1 << ADIE) | (1 << ADPS2) | (1 << ADPS1); // Abilita ADC, interrupt, prescaler 64
// Configurazione Timer1 per il campionamento
TCCR1A = 0;
TCCR1B = (1 << WGM12) | (1 << CS11); // CTC mode, prescaler 8
OCR1A = (F_CPU / (8 * sampling_frequency)) - 1;
TIMSK1 = (1 << OCIE1A); // Abilita interrupt per il confronto A
// Configurazione pin per il Rotary Encoder
DDRD &= ~((1 << ENCODER_PIN_A) | (1 << ENCODER_PIN_B) | (1 << ENCODER_BUTTON_PIN));
PORTD |= (1 << ENCODER_PIN_A) | (1 << ENCODER_PIN_B) | (1 << ENCODER_BUTTON_PIN); // Pull-up
// Abilita interrupt esterni per il Rotary Encoder
EICRA = (1 << ISC00); // Trigger su qualsiasi cambio
EIMSK = (1 << INT0); // Abilita INT0
sei(); // Abilita interrupt globali
}
ISR(TIMER1_COMPA_vect) {
if (sampling && eeprom_address < max_samples) {
ADCSRA |= (1 << ADSC); // Inizia conversione ADC
}
}
ISR(ADC_vect) {
uint16_t value = ADC;
eeprom_write_word((uint16_t*)eeprom_address, value);
eeprom_address += 2;
sample_counter++;
if (eeprom_address >= max_samples * 2) {
sampling = 0;
}
}
ISR(INT0_vect) {
static uint8_t last_encoder_state = 0;
uint8_t encoder_state = PIND & ((1 << ENCODER_PIN_A) | (1 << ENCODER_PIN_B));
if (encoder_state == ((1 << ENCODER_PIN_A) | (1 << ENCODER_PIN_B)) || encoder_state == 0) {
return;
}
if ((last_encoder_state == 0 && encoder_state == (1 << ENCODER_PIN_A)) ||
(last_encoder_state == (1 << ENCODER_PIN_B) && encoder_state == ((1 << ENCODER_PIN_A) | (1 << ENCODER_PIN_B)))) {
if (sampling_frequency < 10000) sampling_frequency += 100;
} else {
if (sampling_frequency > 100) sampling_frequency -= 100;
}
last_encoder_state = encoder_state;
OCR1A = (F_CPU / (8 * sampling_frequency)) - 1;
}
ISR(PCINT2_vect) {
if (!(PIND & (1 << ENCODER_BUTTON_PIN))) {
_delay_ms(50); // Debounce
if (!(PIND & (1 << ENCODER_BUTTON_PIN))) {
sampling = !sampling;
eeprom_address = 0;
sample_counter = 0;
}
}
}
void serial_print(const char* str) {
while (*str) {
while (!(UCSR0A & (1 << UDRE0)));
UDR0 = *str++;
}
}
void serial_println(const char* str) {
serial_print(str);
serial_print("\r\n");
}
void loop() {
static uint16_t last_frequency = 0;
if (last_frequency != sampling_frequency) {
char buffer[20];
snprintf(buffer, sizeof(buffer), "Freq: %d Hz", sampling_frequency);
serial_println(buffer);
last_frequency = sampling_frequency;
}
if (!sampling && eeprom_address > 0) {
char buffer[10];
for (uint16_t i = 0; i < eeprom_address; i += 2) {
uint16_t value = eeprom_read_word((uint16_t*)i);
snprintf(buffer, sizeof(buffer), "%d", value);
serial_println(buffer);
}
eeprom_address = 0;
}
}
int main() {
setup();
while (1) {
loop();
}
return 0;
}