// Define TC0 Channel 0 registers and parameters #include "variant.h" // Pin 9 is PB25, which maps to TIOA0 (Peripheral B) const uint32_t PIN_MASK = PIO_PB25; void setup() { // Initialize Serial communication at 115200 baud Serial.begin(115200); while (!Serial); // 1. Enable peripheral clock for TC0 (Channel 0 is ID 27) PMC->PMC_PCER0 = (1 << ID_TC0); // 2. Configure Pin 9 (PB25) for Peripheral B (TIOA0) PIOB->PIO_ABSR |= PIN_MASK; // Set to Peripheral B PIOB->PIO_PDR |= PIN_MASK; // Disable PIO, enable peripheral control // 3. Configure TC0 Channel 0 in Waveform Mode // Waveform mode, clock MCK/2, toggle TIOA on RC compare match TC0->TC_CHANNEL[0].TC_CMR = TC_CMR_TCCLKS_TIMER_CLOCK1 | // MCK/2 clock source TC_CMR_WAVE | // Waveform mode TC_CMR_WAVSEL_UP_RC | // UP mode with automatic trigger on RC compare TC_CMR_ACPA_CLEAR | // Clear TIOA on RA compare TC_CMR_ACPC_SET; // Set TIOA on RC compare // 4. Set initial frequency (e.g., 1 kHz based on 84MHz / 2 = 42MHz master clock) // Frequency = (MCK / 2) / RC -> For 1 kHz: 42,000,000 / 1000 = 42000 setTimerFrequency(1000); // Enable and start the counter TC0->TC_CHANNEL[0].TC_CCR = TC_TC_CLKEN | TC_TC_SWTRG; Serial.println("Arduino Due TC0 Waveform Generator Initialized."); Serial.println("Send a frequency value (in Hz) via Serial to update the rate."); } void loop() { // Check if data is available on the serial port to change the rate/bits if (Serial.available() > 0) { long inputVal = Serial.parseInt(); if (inputVal > 0) { if (inputVal < 100) { // Example logic: if a small number is sent, treat it as a bit pattern command or scale Serial.print("Received pattern/command scale: "); Serial.println(inputVal); } else { // Treat as frequency in Hz setTimerFrequency(inputVal); Serial.print("Updated frequency to: "); Serial.print(inputVal); Serial.println(" Hz"); } } } } void setTimerFrequency(uint32_t frequencyHz) { // Prevent division by zero or out-of-range values if (frequencyHz == 0) frequencyHz = 1; // The Due's peripheral clock (MCK) is 84 MHz. // TIMER_CLOCK1 uses MCK/2 = 42 MHz. uint32_t rad = 42000000 / frequencyHz; if (rad > 65535) rad = 65535; // RC is a 16-bit register if (rad < 2) rad = 2; // Set RA to 50% duty cycle, RC to the full period count TC0->TC_CHANNEL[0].TC_RA = rad / 2; TC0->TC_CHANNEL[0].TC_RC = rad; // Software trigger to reload values immediately TC0->TC_CHANNEL[0].TC_CCR = TC_TC_SWTRG; }