Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //Arduino Nano R4 Input Capture example - Zack Nelson 2026
- //Input on D7, OLED on A4/5
- #include "Arduino.h"
- #include <math.h>
- #include <U8g2lib.h>
- uint32_t lastTS, currentTS, delta = 0; //input capture readings
- #define readingsMax 16
- uint32_t readingsBuffer[readingsMax] = {}; //store multiple input capture readings
- uint8_t readingsIndex = 0;
- const char* const noteNames[12] = {"A", "A#/Bb", "B", "C", "C#/Db", "D", "D#/Eb", "E", "F", "F#/Gb", "G", "G#/Ab"};
- char buffer[20]; //text buffer
- //Asynchronous General Purpose Timer interrupt (from vector_data.h)
- static const IRQn_Type IRQn_CCMPA = AGT0_INT_IRQn;
- //128x32 I2C OLED on pins A4 (data) & A5 (clock)
- U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE);
- void captureISR() {
- lastTS = currentTS;
- currentTS = R_GPT0->GTCCR[0]; //read from input capture register
- delta = currentTS - lastTS;
- readingsBuffer[readingsIndex++] = delta;
- readingsIndex %= readingsMax; //wrap around at max
- //clear interrupt flag for capture compare match A
- R_ICU->IELSR_b[IRQn_CCMPA].IR = 0;
- }
- void setup() {
- u8g2.begin(); //start OLED
- //Timer Setup------------------------------------------------------------------------------------
- R_MSTP->MSTPCRD_b.MSTPD5 = 0; //enable GPT0 module clock (General PWM Timer 321 to 320 Module Stop)
- delayMicroseconds(10);
- R_GPT0->GTCR_b.CST = 0; //stop timer
- R_GPT0->GTCR_b.MD = 0b000; //saw-wave PWM mode (000b)
- R_GPT0->GTUDDTYC = 0b11; //set 11b first (per datasheet Figure 22.17)
- R_GPT0->GTUDDTYC = 0b01; //01b for up-counting
- //R_GPT0->GTCR_b.TPCS = 0b011; //PCLKD/64 prescale
- R_GPT0->GTPR = 0xFFFFFFFF; //max cycle
- R_GPT0->GTCNT = 0; //0 initial count
- //GTCCRA input capture enabled on the...
- R_GPT0->GTICASR_b.ASCARBL = 1; //rising edge of GTIOCA input when GTIOCB input is 0
- R_GPT0->GTICASR_b.ASCARBH = 1; //rising edge of GTIOCA input when GTIOCB input is 1
- R_GPT0->GTCR_b.CST = 1; //start count operation
- //GPIO Pin D7 (P107) Setup-----------------------------------------------------------------------
- R_PFS->PORT[1].PIN[7].PmnPFS_b.PMR = 1; //Used as an I/O port for peripheral functions
- R_PFS->PORT[1].PIN[7].PmnPFS_b.PSEL = 0b11; //GTIOC0A (GPT peripheral function)
- //Interrupt Setup--------------------------------------------------------------------------------
- //assign GPT0 Capture to IRQn_CCMPA (AGT0_INT_IRQn #17)
- R_ICU->IELSR_b[IRQn_CCMPA].IELS = ELC_EVENT_GPT0_CAPTURE_COMPARE_A;
- NVIC_SetVector(IRQn_CCMPA, (uint32_t)captureISR); //point to the ISR function
- NVIC_SetPriority(IRQn_CCMPA, 12);
- NVIC_EnableIRQ(IRQn_CCMPA);
- }
- void loop() {
- uint64_t averageReading = 0; //get average of all readings
- for (uint8_t i = 0; i < readingsMax; i++) averageReading += readingsBuffer[i];
- averageReading /= readingsMax;
- float freq = 48000000.0/averageReading; //convert from timer count difference to frequency in Hz
- float note = 12 * log2(freq/440); //convert from Hz to note #
- while (note < 0) note += 12; //fix negative modulo weirdness
- int8_t noteRounded = (int)round(note) % 12;
- int8_t deviation = (note - round(note)) * 100; //calculate % out of tune
- //update OLED screen
- u8g2.clearBuffer();
- u8g2.setFont(u8g2_font_6x13_tr);
- sprintf(buffer, "Freq: %.1f", freq);
- u8g2.drawStr(0, 10, buffer);
- sprintf(buffer, "Deviation: %d%%\n", deviation);
- u8g2.drawStr(0, 24, buffer);
- u8g2.setFont(u8g2_font_8x13_tr); //larger font for the note name
- u8g2.drawStr(86, 10, noteNames[noteRounded]);
- u8g2.drawLine(64, 30, 64 + deviation, 30); //Draw thick line to show tuning deviation
- u8g2.drawLine(64, 31, 64 + deviation, 31);
- u8g2.drawLine(64, 32, 64 + deviation, 32);
- u8g2.sendBuffer();
- delay(1000/5); //5Hz refresh
- }
Advertisement
Add Comment
Please, Sign In to add comment