#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
// Definizione dei comandi
#define READ_ROM 0x33
#define READ_SCRATCHPAD 0xBE
// Pin utilizzato per 1-Wire
#define ONEWIRE_PIN PD4
#define ONEWIRE_PORT PORTD
#define ONEWIRE_DDR DDRD
#define ONEWIRE_PIN_INPUT PIND
// Funzioni CRC
uint8_t crc8(const uint8_t *data, uint8_t len);
// Variabili globali per i comandi
volatile uint8_t command = 0;
// ISR per i pulsanti
ISR(INT0_vect) {
command = READ_ROM;
}
ISR(INT1_vect) {
command = READ_SCRATCHPAD;
}
// Funzione per inizializzare l'ADC
void adc_init() {
ADMUX = (1<<REFS0); // AVcc con condensatore su AREF
ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1); // Abilita ADC e prescaler a 64
}
// Funzione per leggere il valore dall'ADC
uint16_t adc_read(uint8_t ch) {
ch &= 0b00000111; // Canale deve essere tra 0 e 7
ADMUX = (ADMUX & 0xF8) | ch; // Seleziona canale
ADCSRA |= (1<<ADSC); // Avvia conversione
while(ADCSRA & (1<<ADSC)); // Aspetta fine conversione
return (ADC);
}
// Funzione per inizializzare gli interrupt
void init_interrupts() {
EIMSK |= (1<<INT0) | (1<<INT1); // Abilita INT0 e INT1
EICRA |= (1<<ISC01) | (1<<ISC11); // Falling edge triggers
sei(); // Abilita gli interrupt globali
}
// Funzione per gestire la comunicazione 1-Wire
void onewire_write_bit(uint8_t bit) {
if (bit) {
// Scrittura di un bit '1'
ONEWIRE_DDR |= (1<<ONEWIRE_PIN); // Imposta il pin come output
ONEWIRE_PORT &= ~(1<<ONEWIRE_PIN); // Porta bassa
_delay_us(6); // Attendi 6 µs
ONEWIRE_PORT |= (1<<ONEWIRE_PIN); // Porta alta
_delay_us(64); // Attendi 64 µs
} else {
// Scrittura di un bit '0'
ONEWIRE_DDR |= (1<<ONEWIRE_PIN); // Imposta il pin come output
ONEWIRE_PORT &= ~(1<<ONEWIRE_PIN); // Porta bassa
_delay_us(60); // Attendi 60 µs
ONEWIRE_PORT |= (1<<ONEWIRE_PIN); // Porta alta
_delay_us(10); // Attendi 10 µs
}
}
uint8_t onewire_read_bit() {
uint8_t bit = 0;
ONEWIRE_DDR |= (1<<ONEWIRE_PIN); // Imposta il pin come output
ONEWIRE_PORT &= ~(1<<ONEWIRE_PIN); // Porta bassa
_delay_us(6); // Attendi 6 µs
ONEWIRE_DDR &= ~(1<<ONEWIRE_PIN); // Imposta il pin come input
_delay_us(9); // Attendi 9 µs
if (ONEWIRE_PIN_INPUT & (1<<ONEWIRE_PIN)) {
bit = 1;
}
_delay_us(55); // Attendi 55 µs
return bit;
}
/*void onewire_write_byte(uint8_t byte) {
for (uint8_t i = 0; i < 8; i++) {
onewire_write_bit(byte & 0x01);
byte >>= 1;
}
}*/
void onewire_write_byte(uint8_t byte) {
for (uint8_t i = 0; i < 8; i++) {
onewire_write_bit(byte & 0x80);
byte <<= 1;
}
}
uint8_t onewire_read_byte() {
uint8_t byte = 0;
for (uint8_t i = 0; i < 8; i++) {
byte |= (onewire_read_bit() << i);
}
return byte;
}
// Funzione principale
int main(void) {
DDRD &= ~((1<<PD2) | (1<<PD3)); // Imposta PD2 e PD3 come input (pulsanti)
PORTD |= (1<<PD2) | (1<<PD3); // Attiva pull-up interni
adc_init(); // Inizializza ADC
init_interrupts(); // Inizializza gli interrupt
ONEWIRE_DDR |= (1<<ONEWIRE_PIN); // Imposta il pin come output
//_delay_us(6); // Attendi 6 µs
ONEWIRE_PORT |= (1<<ONEWIRE_PIN); // Porta alta
//_delay_us(64); // Attendi 64 µs
while (1) {
if (command == READ_ROM) {
command = 0;
uint8_t rom_code[8] = {0x28, 0xFF, 0x6C, 0x50, 0x91, 0x16, 0x04, 0xD2}; // ROM code fittizio
//uint8_t crc = crc8(rom_code, 7);
//rom_code[7] = crc;
for (uint8_t i = 0; i < 8; i++) {
onewire_write_byte(rom_code[i]);
}
} else if (command == READ_SCRATCHPAD) {
command = 0;
uint16_t adc_value = adc_read(0); // Legge il valore del potenziometro
uint8_t scratchpad[9] = {0};
scratchpad[0] = adc_value & 0xFF;
scratchpad[1] = (adc_value >> 8) & 0xFF;
uint8_t crc = crc8(scratchpad, 8);
scratchpad[8] = crc;
for (uint8_t i = 0; i < 9; i++) {
onewire_write_byte(scratchpad[i]);
}
}
}
}
// Funzione per calcolare CRC8
uint8_t crc8(const uint8_t *data, uint8_t len) {
uint8_t crc = 0;
while (len--) {
uint8_t inbyte = *data++;
for (uint8_t i = 8; i; i--) {
uint8_t mix = (crc ^ inbyte) & 0x01;
crc >>= 1;
if (mix) crc ^= 0x8C;
inbyte >>= 1;
}
}
return crc;
}