uint32_t analogRead(uint32_t pin) { uint32_t valueRead = 0; if (pin < A0) { pin += A0; } pinPeripheral(pin, PIO_ANALOG); // Disable DAC, if analogWrite() was used previously to enable the DAC if ((g_APinDescription[pin].ulADCChannelNumber == ADC_Channel0) || (g_APinDescription[pin].ulADCChannelNumber == DAC_Channel0)) { syncDAC(); DAC->CTRLA.bit.ENABLE = 0x00; // Disable DAC //DAC->CTRLB.bit.EOEN = 0x00; // The DAC output is turned off. syncDAC(); } syncADC(); ADC->INPUTCTRL.bit.MUXPOS = g_APinDescription[pin].ulADCChannelNumber; // Selection for the positive ADC input // Control A /* * Bit 1 ENABLE: Enable * 0: The ADC is disabled. * 1: The ADC is enabled. * Due to synchronization, there is a delay from writing CTRLA.ENABLE until the peripheral is enabled/disabled. The * value written to CTRL.ENABLE will read back immediately and the Synchronization Busy bit in the Status register * (STATUS.SYNCBUSY) will be set. STATUS.SYNCBUSY will be cleared when the operation is complete. * * Before enabling the ADC, the asynchronous clock source must be selected and enabled, and the ADC reference must be * configured. The first conversion after the reference is changed must not be used. */ syncADC(); ADC->CTRLA.bit.ENABLE = 0x01; // Enable ADC // Start conversion syncADC(); ADC->SWTRIG.bit.START = 1; // Clear the Data Ready flag ADC->INTFLAG.reg = ADC_INTFLAG_RESRDY; // Start conversion again, since The first conversion after the reference is changed must not be used. syncADC(); ADC->SWTRIG.bit.START = 1; // Store the value while (ADC->INTFLAG.bit.RESRDY == 0); // Waiting for conversion to complete valueRead = ADC->RESULT.reg; syncADC(); ADC->CTRLA.bit.ENABLE = 0x00; // Disable ADC syncADC(); return mapResolution(valueRead, _ADCResolution, _readResolution); }
// Right now, PWM output only works on the pins with // hardware support. These are defined in the appropriate // pins_*.c file. For the rest of the pins, we default // to digital output. void analogFastWrite(uint32_t pin, uint32_t value) { PinDescription pinDesc = g_APinDescription[pin]; uint32_t attr = pinDesc.ulPinAttribute; if ((attr & PIN_ATTR_ANALOG) == PIN_ATTR_ANALOG) { // DAC handling code if (pin != PIN_A0) { // Only 1 DAC on A0 (PA02) return; } value = mapResolution(value, _writeResolution, 10); syncDAC(); DAC->DATA.reg = value & 0x3FF; // DAC on 10 bits. syncDAC(); DAC->CTRLA.bit.ENABLE = 0x01; // Enable DAC syncDAC(); return; } if ((attr & PIN_ATTR_PWM) == PIN_ATTR_PWM) { value = mapResolution(value, _writeResolution, 8); // change to 10 for 10 bit... must also change TCx->COUNT8.PER.reg = 0x3FF uint32_t tcNum = GetTCNumber(pinDesc.ulPWMChannel); uint8_t tcChannel = GetTCChannelNumber(pinDesc.ulPWMChannel); static bool tcEnabled[TCC_INST_NUM+TC_INST_NUM]; if (!tcEnabled[tcNum]) { tcEnabled[tcNum] = true; if (attr & PIN_ATTR_TIMER) { #if !(ARDUINO_SAMD_VARIANT_COMPLIANCE >= 10603) // Compatibility for cores based on SAMD core <=1.6.2 if (pinDesc.ulPinType == PIO_TIMER_ALT) { pinPeripheral(pin, PIO_TIMER_ALT); } else #endif { pinPeripheral(pin, PIO_TIMER); } } else { // We suppose that attr has PIN_ATTR_TIMER_ALT bit set... pinPeripheral(pin, PIO_TIMER_ALT); } uint16_t GCLK_CLKCTRL_IDs[] = { GCLK_CLKCTRL_ID(GCM_TCC0_TCC1), // TCC0 GCLK_CLKCTRL_ID(GCM_TCC0_TCC1), // TCC1 GCLK_CLKCTRL_ID(GCM_TCC2_TC3), // TCC2 GCLK_CLKCTRL_ID(GCM_TCC2_TC3), // TC3 GCLK_CLKCTRL_ID(GCM_TC4_TC5), // TC4 GCLK_CLKCTRL_ID(GCM_TC4_TC5), // TC5 GCLK_CLKCTRL_ID(GCM_TC6_TC7), // TC6 GCLK_CLKCTRL_ID(GCM_TC6_TC7), // TC7 }; GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_IDs[tcNum]); while (GCLK->STATUS.bit.SYNCBUSY == 1); // Set PORT if (tcNum >= TCC_INST_NUM) { // -- Configure TC Tc* TCx = (Tc*) GetTC(pinDesc.ulPWMChannel); // Disable TCx TCx->COUNT8.CTRLA.bit.ENABLE = 0; syncTC_8(TCx); // Set Timer counter Mode to 8 bits, normal PWM TCx->COUNT8.CTRLA.reg |= TC_CTRLA_MODE_COUNT8 | TC_CTRLA_WAVEGEN_NPWM; syncTC_8(TCx); // Set the initial value TCx->COUNT8.CC[tcChannel].reg = (uint8_t) value; syncTC_8(TCx); // Set PER to maximum counter value (resolution : 0xFF) TCx->COUNT8.PER.reg = 0xFF; syncTC_8(TCx); // Enable TCx TCx->COUNT8.CTRLA.bit.ENABLE = 1; syncTC_8(TCx); } else { // -- Configure TCC Tcc* TCCx = (Tcc*) GetTC(pinDesc.ulPWMChannel); // Disable TCCx TCCx->CTRLA.bit.ENABLE = 0; syncTCC(TCCx); // Set TCx as normal PWM TCCx->WAVE.reg |= TCC_WAVE_WAVEGEN_NPWM; syncTCC(TCCx); // Set the initial value TCCx->CC[tcChannel].reg = (uint32_t) value; syncTCC(TCCx); // Set PER to maximum counter value (resolution : 0xFF) TCCx->PER.reg = 0xFF; //change to 0x43FF for 10 bit... must also change mapping above syncTCC(TCCx); // Enable TCCx TCCx->CTRLA.bit.ENABLE = 1; syncTCC(TCCx); } } else { if (tcNum >= TCC_INST_NUM) { Tc* TCx = (Tc*) GetTC(pinDesc.ulPWMChannel); TCx->COUNT8.CC[tcChannel].reg = (uint8_t) value; syncTC_8(TCx); } else { Tcc* TCCx = (Tcc*) GetTC(pinDesc.ulPWMChannel); TCCx->CTRLBSET.bit.LUPD = 1; syncTCC(TCCx); TCCx->CCB[tcChannel].reg = (uint32_t) value; syncTCC(TCCx); TCCx->CTRLBCLR.bit.LUPD = 1; syncTCC(TCCx); } } return; } // -- Defaults to digital write pinMode(pin, OUTPUT); value = mapResolution(value, _writeResolution, 8); if (value < 128) { digitalWrite(pin, LOW); } else { digitalWrite(pin, HIGH); } }