Example #1
0
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);
}
Example #2
0
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);
}
Example #3
0
/** 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);
}
Example #5
0
/***    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));
}
Example #6
0
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;
}
Example #8
0
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);
}
Example #9
0
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);
} 
Example #10
0
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);
}
Example #11
0
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;
}
Example #13
0
//************************************************************************
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);
	} 
}
Example #14
0
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();
}