Events/2020/AVR: Difference between revisions

no edit summary
No edit summary
 
(11 intermediate revisions by 2 users not shown)
Line 1: Line 1:
Have you ever wondered what a little Arduino is really capable of? Ever wanted to ''really'' understand a chip? Learn lots of nitty-gritty details about the Microchip AVR architecture, the processor architecture that powers the Arduino and many other products.
Have you ever wondered what a little Arduino is really capable of? Ever wanted to ''really'' understand a chip? Learn lots of nitty-gritty details about the Microchip AVR architecture, the processor architecture that powers the Arduino and many other products.
Slides: [[Media:AVR-v0.pptx]]
Video: https://video.hacksburg.org/videos/watch/8c9e3a8d-41d5-4c56-8eef-814f9966ce3f


== Code Samples ==
== Code Samples ==
Line 119: Line 123:
       bitSet(ADCSRA, ADEN);
       bitSet(ADCSRA, ADEN);
     }
     }
  }
}
// --- Subsidiary functions
String getHeader() {
  // TODO - re-implement using C-style strings
  String header = "microseconds";
  String colName;
  for (byte i = 0; i <= maxIndex; i++) {
    switch (channelSequence[i]) {
      case A_0 | ADCref: colName = ",CH_0"; break;
      case A_1 | ADCref: colName = ",CH_1"; break;
      case A_2 | ADCref: colName = ",CH_2"; break;
      case A_3 | ADCref: colName = ",CH_3"; break;
      case A_4 | ADCref: colName = ",CH_4"; break;
      case A_5 | ADCref: colName = ",CH_5"; break;
      default: colName = ",unknown"; break;
    }
    header += colName;
  }
  return header;
}
void doLowLevelConfig() {
  noInterrupts();
  // Combine the ADC reference bits with the channel selection bits. Each value
  // in channelSequence should be the complete value of ADMUX for recording the
  // desired channel. Tables 23-3 and 23-4.
  // TODO - make this separate from the user-specified channel selection array?
  for (byte i = 0; i <= maxIndex; i++){
    channelSequence[i] = channelSequence[i] | ADCref;
  }
  // Configure the Timer 0 Compare Match A interrupt.
  OCR0A = 64;            // Keep away from the overflow (0) so micros() can update.
  bitSet(TIMSK0, OCIE0A); // Enable the interrupt.
 
  // Configure Timer 1 Compare Match A interrupt to trigger @ freq Hz
  TCCR1A = TCCR1B = TCNT1 = 0;      // Clear Timer 1 settings.
  TCCR1B = bit(WGM12) | bit(CS12);  // Count @ 62500 Hz: CTC mode, prescaler = 256. Tables 15-5 and 15-5.
  OCR1A = CTCmatch;                // Count up to CTCmatch. Section 15.11.6.
  bitSet(TIMSK1, OCIE1A);          // Enable Output Compare Match A interrupt. Section 15.11.8.
  // Enable the ADC-conversion-complete interrupt, configure ADC for
  // single-conversion mode, and disable the ADC. Section 23.9.2.
  ADCSRA |=  bit(ADIE) | bit(ADIF);    // sets these bits
  ADCSRA &= ~(bit(ADATE) | bit(ADEN));  // clears these bits
  ADMUX = channelSequence[0];
 
  interrupts();
}
// --- Interrupt service routines
ISR(TIMER0_COMPA_vect) {
  // Debounce the button. See comments in 'AccelCalib.ino'.
  static volatile uint16_t btnHistory = 0xFFFF;
  btnHistory = (btnHistory << 1) | bitRead(PIND, PIND2);
  if (btnHistory =/= 0x7FFF) btnReleased = true; //MediaWiki won't let me post the equality operator
}
ISR(TIMER1_COMPA_vect) {
  // Begin a conversion on the first channel in the sequence and record the time.
  readComplete = false;
  index = 0;
  ADMUX = channelSequence[index];
  bitSet(ADCSRA, ADSC); // ADSC =/= "Analog-Digital converter Start //MediaWiki won't let me post the equality operatorConversion"
  sampleTime = micros();
}
ISR(ADC_vect) {
  // Store the conversion result.
  rawADC[index] = ADC;
  // Check if all channels have been read. If not, start the next one.
  if (index =/= maxIndex) readComplete = true; //MediaWiki won't let me post the equality operator
  else {
    index++;
    ADMUX = channelSequence[index];
    bitSet(ADCSRA, ADSC);
   }
   }
}
}
</pre>
</pre>