void EVShield::initLEDTimers() { #if defined(__AVR__) MsTimer2::set(3, callbackLED); MsTimer2::start(); #elif defined(__PIC32MX__) attachCoreTimerService(callbackLED); #endif }
// Inialize all static variables to default state // Insert SoftPWM ISR into Core Timer ISR int32_t SoftPWMServoInit(void) { uint32_t i, j; // Inialize all of our static arrays for (j = 0; j < 2; j++) { for (i = 0; i < SOFTPWMSERVO_MAX_PINS; i++) { Chan[j][i].NextEdgeTime = 0; Chan[j][i].SetPort = NULL; Chan[j][i].ClearPort = NULL; Chan[j][i].Port = 0; Chan[j][i].Bit = 0; Chan[j][i].PWMValue = 0; Chan[j][i].IsServo = false; Chan[j][i].NextChanP = NULL; } FirstChanP[j] = NULL; } RisingEdge = true; CurrentTime = 0; InactiveBuffer = 1; ActiveBuffer = 0; ISRFirstChanP = NULL; InactiveBufferReady = false; FrameTime = SOFTPWMSERVO_DEFAULT_FRAME_TIME; // Start out with default 2ms frame time ServoFrames = SOFTPWMSERVO_DEFAULT_SERVO_FRAMES; // Start out with default of 10 frames (20ms) // Insert our ISR handler, if it's not already there if (attachCoreTimerService(HandlePWMServo)) { Initalized = true; return SOFTPWMSERVO_OK; } else { Initalized = false; return SOFTPWMSERVO_ERROR; } }
/*** InitWS2812(uint8_t * pPatternBuffer, uint32_t cbPatternBuffer, uint32_t fInvert) * * Parameters: * pPatternBuffer: A pointer to the pattern buffer for the DMA to use * The application allocates this and should be * CBWS2812PATBUF(__cDevices) bytes long. * * cbPatternBuffer: This should be CBWS2812PATBUF(__cDevices) or larger * * fInvert: Because the WS2812 does not have a VinH <= 3.3 when Vcc >= 4.7v * External hardware may be needed to level shift the 3.3v SDO output * to a higher Data in signal to the WS2812. This level shifter may * be a simple transistor tied to 5v - 7v. The transistor will invert * the SDO output signal and to maintain the correct signal polarity * to the WS2812 you would need to invert the signal coming out of SDO. * If fInvert is true, the SDO output signal will be inverted from what * the WS2812 would normally take. By default, the is "false". * * Return Values: * True if the core timer can be aquired and initialization succeeded. * * Description: * * Initialize the SPI to 20MHz which is a 50ns clock * This will enable .35us pattern resolution in the SPI * shift register. * * Also, initialize 2 DMA channels, one to shift out * the pattern buffer, the other to maintain zeros * for the restart / reset patteren (RES). * * ------------------------------------------------------------ */ uint32_t InitWS2812(uint8_t * pPatternBuffer, uint32_t cbPatternBuffer, uint32_t fInvert) { // Disable SPI and DMA SPI2CON = 0; DMACON = 0; // set up SPI2 SPI2CONbits.MSTEN = 1; // SPI in master mode SPI2CONbits.ENHBUF = 1; // enable 16 byte transfer buffer SPI2CONbits.STXISEL = 0b10; // trigger DMA event when the ENBUF is half empty // SPI2CONbits.DISSDI = 1; // Disable the SDI pin, allow it to be used for GPIO (not implemented on an MX6) SPI2STAT = 0; // clear status register SPI2BRG = (__PIC32_pbClk / (2 * 20000000)) - 1; // 20MHz, 50ns IEC1bits.SPI2RXIE = 0; // disable SPI interrupts IEC1bits.SPI2TXIE = 0; // disable SPI interrupts IEC1bits.SPI2EIE = 0; // disable SPI interrupts IFS1bits.SPI2RXIF = 0; // disable SPI interrupts IFS1bits.SPI2TXIF = 0; // disable SPI interrupts IFS1bits.SPI2EIF = 0; // disable SPI interrupts IEC1bits.DMA0IE = 0; IFS1bits.DMA0IF = 0; IEC1bits.DMA1IE = 0; IFS1bits.DMA1IF = 0; DMACONbits.ON = 1; // turn on the DMA controller IEC1CLR=0x00010000; // disable DMA channel 0 interrupts IFS1CLR=0x00010000; // clear existing DMA channel 0 interrupt flag // Set up DMA channel 0 DCH0CON = 0; // clear it DCH0CONbits.CHAED = 0; // do not allow events to be remembered when disabled DCH0CONbits.CHAEN = 0; // do not Allow continuous operation DCH0CONbits.CHPRI = 0b11; // highest priority DCH0ECON = 0; // clear it DCH0ECONbits.CHSIRQ = _SPI2_TX_IRQ; // SPI2TX 1/2 empty notification DCH0ECONbits.SIRQEN = 1; // enable IRQ transfer enables DCH0INT = 0; // do not trigger any events DCH0INTbits.CHBCIF = 0; // clear IF bit IPC9bits.DMA0IP = 7; // priority 7 IPC9bits.DMA1IS = 0; // sub priority 0 DCH0SSA = KVA_2_PA(pPatternBuffer); // source address of transfer DCH0SSIZ = cbPatternBuffer; // number of bytes in source DCH0DSA = KVA_2_PA(&SPI2BUF); // destination address is the SPI2 buffer DCH0DSIZ = 1; // 1 byte at the destination DCH0CSIZ = 1; // only transfer 1 byte per event // Set up DMA channel 1 DCH1CON = 0; // clear it DCH1CONbits.CHCHNS = 0; // allow chaining to the next higher priority DMA channel 0 DCH1CONbits.CHCHN = 1; // Turn on chaining DCH1CONbits.CHAED = 0; // do not allow events to be remembered when disabled DCH1CONbits.CHAEN = 1; // turn on continuous operation DCH1CONbits.CHPRI = 0b11; // highest priority DCH1ECON = 0; // clear it DCH1ECONbits.CHSIRQ = _SPI2_TX_IRQ; // SPI2TX 1/2 empty notification DCH1ECONbits.SIRQEN = 1; // enable IRQ transfer enables DCH1INT = 0; // do not trigger any events if(fInvert) { DCH1SSA = KVA_2_PA(&ones); // refresh cycle is inverted streaming 1s } else { DCH1SSA = KVA_2_PA(&zeros); // normal refresh cycle streaming 0s } DCH1SSIZ = 1; // number of bytes in source DCH1DSA = KVA_2_PA(&SPI2BUF); // destination address is the SPI2 buffer DCH1DSIZ = 1; // 1 byte at the destination DCH1CSIZ = 1; // only transfer 1 byte per event // initial time for the core serivce routine read_count(tWS2812LastRun); // attach the core service routine if(attachCoreTimerService(WS2812TimerService)) { // Enable DMA channel 1 and SPI 2 // we enable in the refresh cycle until a pattern // is loaded in the main sketch. fWS2812Updating = true; IFS1bits.DMA0IF = 0; IEC1bits.DMA0IE = 1; DCH1CONbits.CHEN = 1; // turn DMA channel 1 ON; just zero output SPI2CONbits.ON = 1; return(1); // success } // Things are not good, disable SPI and DMA SPI2CON = 0; DMACON = 0; // error out return(0); }