#define N_SAMPLES_QT 78
uint16_t sineTable[N_SAMPLES_QT];
volatile uint16_t pwmTables[2][N_SAMPLES_QT];
void generateSineTable();
bool updateSignalAttenuation(uint8_t);
volatile uint8_t sampleIndex = 0;
#define GP_FLAGS GPIOR0
#define IMUX7S 0
#define WAVE_DIR 1
#define WAVE_VECT_ROW_IDX 2
#define WAVE_OUT_PIN 3
void setup() {
// Enable All Output Pins used
DDRD |= 0xfc; // PD2 - PD7 ; All for segm. display
DDRB |= 0x1f; // PB0 - PB4 ; PB0 PB3 PB4 display, PB1 PB2 PWM Signal
generateSineTable();
Serial.begin(115200);
cli(); //stop interrupts for till we make the settings
// TIMER 0 - Used for Segm. Display management and ADC
TIMSK0 |= (1 << OCIE0B); // Enable compare match B Interrupt
// TIMER 1 - Used for PWM Signal Output
TCCR1A = 0; // Reset entire TCCR1A to 0
TCCR1B = 0; // Reset entire TCCR1B to 0
TCCR1A |= (1 << WGM11) | (1 << WGM10);
TCCR1A |= (1 << COM1A1) | (1 << COM1B1); // Clear OC1A/OC1B on compare match, set OC1A/OC1B at BOTTOM (non-inverting mode)
TCCR1B |= (1 << WGM12); // ENABLES FAST PWM MODE
TCCR1B |= (1 << CS10); // no prescaling
TIMSK1 |= (1 << TOIE1); //Set TOIE1 to 1 -> overflow interrupt
// ADC Config
ADMUX = 0;
ADMUX |= (1 << REFS0); // Reference voltage AVCC with external capacitor at AREF pin
ADCSRA |= (1 << ADEN); // Set ADEN in ADCSRA (0x7A) to enable the ADC. Note, this instruction takes 12 ADC clocks to execute
ADCSRA |= (1 << ADIE); // Set ADIE in ADCSRA (0x7A) to enable the ADC interrupt. Without this, the internal interrupt will not trigger.
sei(); //Enable back the interrupts
}
uint8_t currentFeedbackAttenuation = 0;
volatile uint16_t adcResult = 0;
const uint8_t digitAlphabeth[10] = { 0x3F, 0x6, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x7, 0x7F, 0x6F };
volatile uint8_t digit[2] = { digitAlphabeth[0], digitAlphabeth[0] };
void loop() {
cli(); // zona critica
const uint16_t a = adcResult;
sei(); // fine zona critica
//const uint8_t tempFeedbackAttenuation = map(a, 0, 1023, 0, 20) + 0.5;
const uint8_t tempFeedbackAttenuation = (a / (1023 / 20)) + 0.5;
if(tempFeedbackAttenuation != currentFeedbackAttenuation){
currentFeedbackAttenuation = tempFeedbackAttenuation;
uint8_t num = currentFeedbackAttenuation;
for(uint8_t i = 0; i < 2; i++){
cli();
digit[i] = digitAlphabeth[num % 10];
sei();
num /= 10;
}
updateSignalAttenuation(currentFeedbackAttenuation);
}
}
// ----------------------------------------------------------------------------------------------
#define MUX7S 8
#define ADC_RATE 200
volatile uint8_t mux_counter = MUX7S, adc_start = ADC_RATE;
#define PD_BITMASK 0xfc
#define PB_BITMASK 0x01
ISR(TIMER0_COMPB_vect){
if(--mux_counter == 0){
const uint8_t d = ~ digit[bitRead(GP_FLAGS, IMUX7S)];
//turn off display
bitClear(PORTB, PB3);
bitClear(PORTB, PB4);
// Clean digits
PORTD |= PD_BITMASK;
PORTB |= PB_BITMASK;
// Print digits
PORTD &= (d << PD2) & PD_BITMASK;
PORTB &= (d >> 6) & PB_BITMASK;
bitWrite(PORTB, PB3, bitRead(GP_FLAGS, IMUX7S));
bitWrite(PORTB, PB4, !bitRead(GP_FLAGS, IMUX7S));
bitToggle(GP_FLAGS, IMUX7S);
mux_counter = MUX7S;
}
if(--adc_start == 0){
bitSet(ADCSRA, ADSC);
adc_start = ADC_RATE;
}
}
ISR(TIMER1_OVF_vect){
*(&OCR1A + bitRead(GP_FLAGS, WAVE_OUT_PIN)) = pwmTables[bitRead(GP_FLAGS, WAVE_VECT_ROW_IDX)][sampleIndex];
if(sampleIndex == 0){
bitClear(GP_FLAGS, WAVE_DIR);
bitToggle(GP_FLAGS, WAVE_OUT_PIN);
}
else if(sampleIndex == N_SAMPLES_QT - 1){
bitSet(GP_FLAGS, WAVE_DIR);
}
sampleIndex += bitRead(GP_FLAGS, WAVE_DIR) ? -1 : 1;
}
// Interrupt service routine for the ADC completion
ISR(ADC_vect){
adcResult = ADC;
}
// ----------------------------------------------------------------------------------------------
void generateSineTable(){
for (uint8_t i = 0; i < N_SAMPLES_QT; i++){
const double sinVal = sin(M_PI * (1.f / N_SAMPLES_QT / 2) * i);
const uint16_t pwmValue = 1023 * sinVal + 0.5;
sineTable[i] = pwmValue;
pwmTables[0][i] = pwmValue;
pwmTables[1][i] = pwmValue;
}
}
bool updateSignalAttenuation(uint8_t attenuationFactor){
if(attenuationFactor > 20)
return false;
const float factor = attenuationFactor / 100.f;
for (uint8_t i = 0; i < N_SAMPLES_QT; i++){
pwmTables[!bitRead(GP_FLAGS, WAVE_VECT_ROW_IDX)][i] = sineTable[i] - sineTable[i] * factor;
}
bitToggle(GP_FLAGS, WAVE_VECT_ROW_IDX);
return true;
}