void nRF24L01::isrHandler() { uint8_t isrstat = 0; uint8_t fifostat = 0; regRead(REG_STATUS, &isrstat, 1); regRead(REG_FIFO_STATUS, &fifostat, 1); // TX done if (isrstat & (1<<5)) { selectRX(); enablePipe(0, _bc, false); enablePipe(1, _addr, true); } // Did we receive data? if (isrstat & (1<<6)) { // We're not actually going to do anything here. } if (isrstat & (1<<4)) { // Too many retries selectRX(); enablePipe(0, _bc, false); enablePipe(1, _addr, true); uint32_t s = disableInterrupts(); digitalWrite(_csn, LOW); _status = _spi->transfer(CMD_TX_FLUSH); digitalWrite(_csn, HIGH); restoreInterrupts(s); } // Clear interrupts isrstat = 0x70; regWrite(REG_STATUS, &isrstat, 1); }
void nRF24L01::unicastPacket(uint8_t *addr, uint8_t *packet) { uint8_t stat = 0; regRead(REG_FIFO_STATUS, &stat, 1); uint32_t timeout = millis(); while (_mode == 1 && millis() - timeout < 1000); // Wait for it to not be transmitting if (_mode == 1) { selectRX(); } regWrite(REG_TX_ADDR, addr, 5); enablePipe(0, addr, true); enablePipe(1, _addr, true); selectTX(); uint32_t s = disableInterrupts(); digitalWrite(_csn, LOW); _status = _spi->transfer(CMD_TX); for (int i = 0; i < _pipeWidth; i++) { _spi->transfer(packet[i]); } digitalWrite(_csn, HIGH); restoreInterrupts(s); digitalWrite(_ce, HIGH); delayMicroseconds(20); digitalWrite(_ce, LOW); }
/** Fill up transmit packet buffer with bytes obtained from the transmit * FIFO buffer, then queue the packet for transmission, if necessary. */ static void fillTransmitPacketBufferAndTransmit(void) { uint32_t status; uint32_t count; uint32_t i; // Put everything in a critical section so that bytes are either in // the transmit FIFO or in interrupt_packet_buffer. status = disableInterrupts(); i = 1; while ((i < sizeof(interrupt_packet_buffer)) && !isCircularBufferEmpty(&transmit_fifo)) { // Note that is_irq is set because interrupts are disabled; that's // equivalent to an interrupt request handler context. interrupt_packet_buffer[i] = circularBufferRead(&transmit_fifo, 1); i++; } count = i - 1; interrupt_packet_buffer[0] = (uint8_t)count; if (count > 0) { // Set transmit_queued before queueing transmit to avoid race // condition where packet is transmitted just after // usbQueueTransmitPacket() call. interrupt_transmit_queued = 1; usbQueueTransmitPacket(interrupt_packet_buffer, count + 1, TRANSMIT_ENDPOINT_NUMBER, 0); } else { interrupt_transmit_queued = 0; } restoreInterrupts(status); }
/** Begin collecting #ADC_SAMPLE_BUFFER_SIZE samples, filling * up #adc_sample_buffer. This will return before all the samples have been * collected, allowing the caller to do something else while samples are * collected in the background. isADCBufferFull() can be used to determine * when #adc_sample_buffer is full. * * It is okay to call this while the sample buffer is still being filled up. * In that case, calling this will abort the current fill and commence * filling from the start. */ void beginFillingADCBuffer(void) { uint32_t status; status = disableInterrupts(); DCH0CONbits.CHEN = 0; // disable channel asm("nop"); // just to be safe DCH0ECONbits.CABORT = 1; // abort any existing transfer and reset pointers // Delay a couple of cycles, just to be safe. DMA transfers are observed // to require up to 7 cycles (depending on source/destination alignment). asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); DCH0ECONbits.CABORT = 0; DCH0INTCLR = 0x00ff00ff; // clear existing events, disable all interrupts DCH0SSA = VIRTUAL_TO_PHYSICAL(&ADC1BUF0); // transfer source physical address DCH0DSA = VIRTUAL_TO_PHYSICAL(&adc_sample_buffer); // transfer destination physical address DCH0SSIZ = sizeof(uint16_t); // source size DCH0DSIZ = sizeof(adc_sample_buffer); // destination size DCH0CSIZ = sizeof(uint16_t); // cell size (bytes transferred per event) DCH0CONbits.CHEN = 1; // enable channel restoreInterrupts(status); }
/*** uint32_t WS2812TimerService(uint32_t curTime) * * Parameters: * The current core timer time * * Return Values: * The next core timer time to be called * * Description: * This is the CoreTimer routine to handle refreshing the * WS2812. This gets called every TICKSPERREFRESH * unless it is behind on a refresh because of external factors * then it is called every TICKSPERSHORTCHECK until it is refreshed. * * ------------------------------------------------------------ */ uint32_t WS2812TimerService(uint32_t curTime) { uint32_t deltaTime = curTime - tWS2812LastRun; // it is time to refresh if(!fWS2812Updating && !DCH0CONbits.CHEN && deltaTime >= TICKSPERREFRESH) { uint32_t intState = disableInterrupts(); DCH1CONbits.CHEN = 0; DCH0CONbits.CHEN = 1; restoreInterrupts(intState); tWS2812LastRun += (deltaTime / TICKSPERREFRESH) * TICKSPERREFRESH; return(tWS2812LastRun + TICKSPERREFRESH); } // if this is in a holding pattern for a really long time // don't let delta get too big and wrap the uint32_t counter if(deltaTime >= (2 * TICKSPERREFRESH)) { tWS2812LastRun += TICKSPERREFRESH; deltaTime -= TICKSPERREFRESH; } // if we get here, we are trying to refresh and are running behind // check more often to get the refresh done. return(tWS2812LastRun + (((deltaTime / TICKSPERSHORTCHECK) + 1) * TICKSPERSHORTCHECK)); }
void LowPower_::sleepWithTheDog() { WDTCONSET = 1<<15; // Turn on WDTCONSET = 0x01; // Kick the dog! int r = disableInterrupts(); enterSleepMode(); restoreInterrupts(r); WDTCONCLR = 1<<15; // Turn off }
// Set a new PWM value for a given pin // Primarily this consists of updating the PWMValue and then // re-sorting the list of active pins by removing and then adding // the pin to the linked list. int32_t SoftPWMServoRawWrite(uint32_t Pin, uint32_t Value, bool PinType) { int i; int32_t intr; // Insert our ISR handler, if it's not already there if (!Initalized) { SoftPWMServoInit(); } // Limit check the inputs if (Value > FrameTime) { Value = FrameTime; } if (Pin > SOFTPWMSERVO_MAX_PINS) { return SOFTPWMSERVO_ERROR; } // And if this pin already has this PWM Value, then don't do anything. if (Value == Chan[ActiveBuffer][Pin].PWMValue) { return SOFTPWMSERVO_OK; } // The easy way to prevent the ISR from doing a buffer swap while // we're in the middle of this is to disable interrupts during // the time that we're mucking with the list. // TODO: Switch to using 3 buffers - one 'active' that the ISR // is currently using, one 'primed' that the mainline code doesn't // touch but has updates and is ready to be swapped before the // next rising edge, and then 'inactive' which is the one we modify // with here. Maybe we wouldn't need to disable interrupts then. intr = disableInterrupts(); // If needed, copy the values from the previously active buffer // into the inactive buffer before we begin work on it. CopyBuffers(); // Always make sure this pin's enabled SoftPWMServoPinEnable(Pin, PinType); // Update the PWM value for this pin Chan[InactiveBuffer][Pin].PWMValue = Value; Chan[InactiveBuffer][Pin].IsServo = PinType; // Remove it from the list Remove(Pin); // And add it back in the list, in the right place (in time) Add(Pin); restoreInterrupts(intr); return SOFTPWMSERVO_OK; }
void nRF24L01::regWrite(uint8_t reg, uint8_t *buffer, uint8_t len) { uint32_t s = disableInterrupts(); digitalWrite(_csn, LOW); _status = _spi->transfer((reg & 0x1F) | 0x20); for (int i = 0; i < len; i++) { _spi->transfer(buffer[i]); } digitalWrite(_csn, HIGH); restoreInterrupts(s); }
void LowPower_::restoreSystemClock() { int i = disableInterrupts(); SYSKEY = 0x0; SYSKEY = 0xAA996655; SYSKEY = 0x556699AA; OSCCONbits.NOSC = _originalClockSettings; OSCCONbits.OSWEN = 1; SYSKEY = 0x0; restoreInterrupts(i); while (OSCCONbits.OSWEN == 1); }
bool LowPower_::switchToLPRC() { int i = disableInterrupts(); _originalClockSettings = OSCCONbits.COSC; SYSKEY = 0x0; SYSKEY = 0xAA996655; SYSKEY = 0x556699AA; OSCCONbits.NOSC = 0b101; OSCCONbits.OSWEN = 1; SYSKEY = 0x0; restoreInterrupts(i); while (OSCCONbits.OSWEN == 1); return (OSCCONbits.COSC == 0b101); }
void nRF24L01::readPacket(uint8_t *buffer) { uint32_t s = disableInterrupts(); digitalWrite(_ce, LOW); digitalWrite(_csn, LOW); _status = _spi->transfer(CMD_RX); for (int i = 0; i < _pipeWidth; i++) { buffer[i] = _spi->transfer(0xFF); } digitalWrite(_csn, HIGH); digitalWrite(_ce, HIGH); restoreInterrupts(s); }
// Disable the SoftPWM functionality on a particular pin number int32_t SoftPWMServoPinDisable(uint32_t Pin) { int32_t intr; intr = disableInterrupts(); CopyBuffers(); // Pull this one out of the linked list of active channels Remove(Pin); // Mark it as unused Chan[InactiveBuffer][Pin].SetPort = NULL; Chan[InactiveBuffer][Pin].ClearPort = NULL; restoreInterrupts(intr); return SOFTPWMSERVO_OK; }
//************************************************************************ void Servo::writeMicroseconds(int value) { // calculate and store the values for the given channel byte channel = this->servoIndex; if ( (channel >= 0) && (channel < MAX_SERVOS) ) // ensure channel is valid { if ( value < SERVO_MIN() ) // ensure pulse width is valid value = SERVO_MIN(); else if ( value > SERVO_MAX() ) value = SERVO_MAX(); value = value - TRIM_DURATION; value = usToTicks(value); // convert to ticks after compensating for interrupt overhead unsigned int status; status = disableInterrupts(); servos[channel].ticks = value; restoreInterrupts(status); } }
void nRF24L01::begin(uint8_t ad0, uint8_t ad1, uint8_t ad2, uint8_t ad3, uint8_t ad4, uint8_t chan, uint8_t width) { _spi->begin(); _spi->setSpeed(10000000UL); _addr[0] = ad0; _addr[1] = ad1; _addr[2] = ad2; _addr[3] = ad3; _addr[4] = ad4; _pipeWidth = width; pinMode(_csn, OUTPUT); pinMode(_ce, OUTPUT); pinMode(_intr, INPUT); digitalWrite(_csn, HIGH); digitalWrite(_ce, HIGH); setChannel(chan); regSet(REG_CONFIG, 2); uint8_t zero = 0x00; regWrite(REG_EN_AA, &zero, 1); _bc[0] = 0xFF; _bc[1] = 0xFF; _bc[2] = 0xFF; _bc[3] = 0xFF; _bc[4] = 0xFF; enablePipe(0, _bc, false); enablePipe(1, _addr, true); selectRX(); switch (isrHandlerCounter) { case 0: isrObject0 = this; attachInterrupt(_intr, nRF24L01_isrHandler0, FALLING); break; case 1: isrObject1 = this; attachInterrupt(_intr, nRF24L01_isrHandler1, FALLING); break; case 2: isrObject2 = this; attachInterrupt(_intr, nRF24L01_isrHandler2, FALLING); break; case 3: isrObject3 = this; attachInterrupt(_intr, nRF24L01_isrHandler3, FALLING); break; case 4: isrObject4 = this; attachInterrupt(_intr, nRF24L01_isrHandler4, FALLING); break; case 5: isrObject5 = this; attachInterrupt(_intr, nRF24L01_isrHandler5, FALLING); break; case 6: isrObject6 = this; attachInterrupt(_intr, nRF24L01_isrHandler6, FALLING); break; case 7: isrObject7 = this; attachInterrupt(_intr, nRF24L01_isrHandler7, FALLING); break; } isrHandlerCounter++; uint32_t s = disableInterrupts(); digitalWrite(_csn, LOW); _status = _spi->transfer(CMD_TX_FLUSH); digitalWrite(_csn, HIGH); digitalWrite(_csn, LOW); _status = _spi->transfer(CMD_RX_FLUSH); digitalWrite(_csn, HIGH); restoreInterrupts(s); uint8_t isrstat = 0x70; regWrite(REG_STATUS, &isrstat, 1); isrstat = 0xFF; regWrite(REG_SETUP_RETR, &isrstat, 1); enablePower(); }