#include "variant.h" // Arduino Due: // Pin 9 = PB25 = TIOA0 (Peripheral B) const uint32_t PIN_MASK = PIO_PB25; const uint32_t TIMER_CLOCK = 42000000UL; // MCK/2 // Maximum programmable bit pattern const uint32_t MAX_BITS = 256; volatile uint8_t bitBuffer[MAX_BITS]; volatile uint32_t bitCount = 0; volatile uint32_t bitIndex = 0; volatile bool transmitting = false; uint32_t bitRate = 1000; // --------------------------------------------------------- // SETUP // --------------------------------------------------------- void setup() { Serial.begin(115200); while (!Serial); // Enable TC0 peripheral clock PMC->PMC_PCER0 = (1 << ID_TC0); // PB25 -> Peripheral B -> TIOA0 PIOB->PIO_ABSR |= PIN_MASK; PIOB->PIO_PDR |= PIN_MASK; // ------------------------------------------------------- // TC0 Channel 0 // // TIMER_CLOCK1 = MCK/2 = 42 MHz // // UP mode with RC reset // ------------------------------------------------------- TC0->TC_CHANNEL[0].TC_CMR = TC_CMR_TCCLKS_TIMER_CLOCK1 | TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC; setBitRate(bitRate); // Enable timer interrupt on RC compare TC0->TC_CHANNEL[0].TC_IER = TC_IER_CPCS; NVIC_EnableIRQ(TC0_IRQn); // Start timer TC0->TC_CHANNEL[0].TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG; // Start with output low PIOB->PIO_CODR = PIN_MASK; Serial.println("Due programmable bit waveform generator"); Serial.println("Pin 9 = TIOA0"); Serial.println(); Serial.println("Commands:"); Serial.println(" RATE "); Serial.println(" BITS "); Serial.println(" SEND"); Serial.println(" STOP"); Serial.println(); } // --------------------------------------------------------- // MAIN LOOP // --------------------------------------------------------- void loop() { if (Serial.available()) { String command = Serial.readStringUntil('\n'); command.trim(); if (command.startsWith("RATE ")) { uint32_t newRate = command.substring(5).toInt(); if (newRate > 0) { bitRate = newRate; setBitRate(bitRate); Serial.print("Bit rate = "); Serial.print(bitRate); Serial.println(" bits/sec"); } } else if (command.startsWith("BITS ")) { String pattern = command.substring(5); pattern.trim(); loadPattern(pattern); Serial.print("Loaded "); Serial.print(bitCount); Serial.println(" bits"); } else if (command == "SEND") { startTransmission(); } else if (command == "STOP") { stopTransmission(); } } } // --------------------------------------------------------- // SET BIT RATE // --------------------------------------------------------- void setBitRate(uint32_t rate) { if (rate == 0) rate = 1; uint32_t rc = TIMER_CLOCK / rate; // RC is 16-bit if (rc > 65535) rc = 65535; if (rc < 2) rc = 2; TC0->TC_CHANNEL[0].TC_RC = rc; } // --------------------------------------------------------- // LOAD BINARY PATTERN // // Example: // // BITS 101101001011 // --------------------------------------------------------- void loadPattern(const String &pattern) { noInterrupts(); bitCount = 0; for (uint32_t i = 0; i < pattern.length() && bitCount < MAX_BITS; i++) { if (pattern[i] == '0') { bitBuffer[bitCount++] = 0; } else if (pattern[i] == '1') { bitBuffer[bitCount++] = 1; } } interrupts(); } // --------------------------------------------------------- // START TRANSMISSION // --------------------------------------------------------- void startTransmission() { if (bitCount == 0) { Serial.println("No bit pattern loaded."); return; } noInterrupts(); bitIndex = 0; transmitting = true; // Put first bit on output immediately if (bitBuffer[0]) PIOB->PIO_SODR = PIN_MASK; else PIOB->PIO_CODR = PIN_MASK; interrupts(); // Reset timer so first bit gets a complete bit period TC0->TC_CHANNEL[0].TC_CCR = TC_CCR_SWTRG; Serial.println("Transmission started"); } // --------------------------------------------------------- // STOP TRANSMISSION // --------------------------------------------------------- void stopTransmission() { noInterrupts(); transmitting = false; bitIndex = 0; // Output low when stopped PIOB->PIO_CODR = PIN_MASK; interrupts(); Serial.println("Transmission stopped"); } // --------------------------------------------------------- // TC0 INTERRUPT // --------------------------------------------------------- void TC0_Handler() { // Reading SR acknowledges the interrupt uint32_t status = TC0->TC_CHANNEL[0].TC_SR; if (status & TC_SR_CPCS) { if (!transmitting) return; bitIndex++; if (bitIndex >= bitCount) { // Finished transmitting = false; bitIndex = 0; PIOB->PIO_CODR = PIN_MASK; return; } // Output next bit if (bitBuffer[bitIndex]) PIOB->PIO_SODR = PIN_MASK; else PIOB->PIO_CODR = PIN_MASK; } }