コード例 #1
0
/***    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);
}
コード例 #2
0
ファイル: ECADC.c プロジェクト: EmbeddedMan/chipKIT32-MAX
/***	convertWiFIREadcEC
**
**	Parameters:
**		channelNumber - The PIC32 analog channel number as in the PIC32 datasheet
**
**	Return Value:
**      The converted value for that channel
**
**	Errors:
**     If return value of zero and error may have occured
**
**	Description:
**      Coverts the analog signal to a digital value on the 
**      given pic32 analog channel number
*/
static int convertWiFIREadcEC(uint8_t channelNumber)
{ 
    int i,k         = 0;
    uint8_t vcn     = channelNumber;
    int analogValue = 0;

    #define KVA_2_PA(v)             (((uint32_t) (v)) & 0x1fffffff)
    static uint16_t __attribute__((coherent)) ovsampValue;

    // set the channel trigger for GSWTRG source triggering
    if(channelNumber == 43 || channelNumber == 44 || channelNumber >= 50)
    {
        return(0);
    }
    else if(channelNumber >= 45 )
    {
        vcn = channelNumber - 45;
        AD1IMOD |= 1 << ((vcn * 2) + 16);               // say use the alt; set SHxALT
    }

    AD1CON3bits.ADINSEL = vcn;                      // manually trigger the conversion
    AD1CON1bits.FILTRDLY = AD1CON2bits.SAMC + 5;    // strictly not needed, but set the timing anyway

    // set up for 16x oversample
    AD1FLTR6            = 0;        // clear oversampling
    AD1FLTR6bits.OVRSAM = 1;        // say 16x oversampling
    AD1FLTR6bits.CHNLID = vcn;      // the ANx channel

    // setup DMA
    IEC4bits.DMA7IE = 0;    // disable DMA channel 4 interrupts
    IFS4bits.DMA7IF = 0;    // clear existing DMA channel 4 interrupt flag

    // setup DMA channel x
    DMACONbits.ON       = 1;                        // make sure the DMA is ON
    DCH7CON             = 0;                        // clear DMA channel CON
    DCH7ECON            = 0;                        // clear DMA ECON
    DCH7ECONbits.CABORT = 1;                        // reset the DMA channel
    while(DCH7CONbits.CHEN == 1);                   // make sure DMA is not enabled
    while(DCH7CONbits.CHBUSY == 1);                 // make sure DMA is not busy
    DCH7CONbits.CHPRI   = 3;                        // use highest priority
    DCH7ECONbits.CHSIRQ = _ADC1_DF6_VECTOR;         // say the ADC filter complete triggers the DMA
    DCH7ECONbits.SIRQEN = 1;                        // enable the IRQ event for triggering
    DCH7SSA             = KVA_2_PA(&AD1FLTR6);      // address of the source
    DCH7SSIZ            = 2;                        // source size is 2 bytes
    DCH7CSIZ            = 2;                        // cell size transfer
    DCH7DSA             = KVA_2_PA(&ovsampValue);   // destination address
    DCH7DSIZ            = sizeof(ovsampValue);      // destination size

    // must throw out first 16 samples
    // keep the 17th. We can not access any ADC registers
    // however we can look at the DMA to see when things complete
    for(i=0; i<17; i++)
    {
        do {

            DCH7ECONbits.CABORT = 1;                    // reset the DMA channel
            AD1FLTR6bits.AFEN   = 0;                    // make sure oversampling is OFF
            while(DCH7CONbits.CHEN == 1);               // wait for DMA to stop
            while(DCH7CONbits.CHBUSY == 1);             // wait for DMA not to be busy
            DCH7INT             = 0;                    // clear all interrupts
            DCH7CONbits.CHEN    = 1;                    // enable the DMA channel
            AD1FLTR6bits.AFEN   = 1;                    // enable oversampling

            AD1CON3bits.RQCONVRT = 1;                   // start conversion

            // we have noticed problems that the DMA channel is not always
            // triggered, so after a time out value, just try again.
            // fundamentally the problem is that AD1FLTR6bits.AFEN must
            // be reset for each oversample conversion, disable and reenabled.

            // we know a conversion is going to take 8000ns * 16, or 128 us
            // we don't want to check too often so DMA and ADC can work
            // but we don't want to wait too long and hold things up

            for(k=0; k<20; k++)                         // this is more than enough time for the conversion, 
            {                                           // really 8 should be good enough
                delayMicroseconds(16);                  // this will cause us to check about 8 times
                if(DCH7INTbits.CHBCIF == 1)
                {
                    break;                              // DMA completed and copied the oversampled result
                }
            }
        } while(DCH7INTbits.CHBCIF == 0);               // if the conversion did not finish, try again
    }
    analogValue = ovsampValue >> 2;                     // 16 oversample gets you 2 extra bits

    // we are done, clean up the DMA, oversampling filter, and ADC
    DCH7CON             = 0;
    while(DCH7CONbits.CHBUSY == 1);
    AD1CON3bits.ADINSEL = 0;
    AD1FLTR6            = 0;

    if(channelNumber >= 45 )
    {
        AD1IMOD &= ~(0b11 << ((vcn * 2) + 16));               // don't use alt
    }

    return(analogValue);
}
コード例 #3
0
/***    void flashOperation(uint32 nvmop, uint32 addr, uint32 data)
**
**    Synopsis:   
**      Performs either a page erase, word write, or row write
**
**    Parameters:
**      nvmop    either NVMOP_PAGE_ERASE, NVMOP_WORD_PGM, or NVMOP_ROW_PGM
**        addr    the uint32_t flash address of: the page to erase, word location to write, or row location to write
**        data    a uint32_t of data to write, or the uint32_t of the SRAM address containing the array of data to write to the row
**
**    Return Values:
**      True if successful, false if failed
**
**    Errors:
**      None
**
**  Notes:
**      data has no meaning when page erase is specified and should be set to 0ul
**
*/
uint32_t FlashOperation(uint32_t nvmop, uint32_t addr, uint32_t data)
{
    unsigned long   t0;
    unsigned int    status;

    #if defined(_PCACHE)
        unsigned long   K0;
        unsigned long   PFEN = CHECON & _CHECON_PREFEN_MASK;
    #endif

    // Convert Address to Physical Address
    NVMADDR = KVA_2_PA(addr);
    NVMDATA = data;
    NVMSRCADDR = KVA_2_PA(data);

    // Suspend or Disable all Interrupts
    SuspendINT(status);

    #if defined(_PCACHE)
        // disable predictive prefetching, see errata
        CHECONCLR = _CHECON_PREFEN_MASK;

        // turn off caching, see errata
        ReadK0(K0);
        WriteK0((K0 & ~0x07) | K0_UNCACHED);
    #endif

     // Enable Flash Write/Erase Operations
    NVMCON = NVMCON_WREN | nvmop;

    // this is a poorly documented yet very important
    // required delay on newer silicon.
    // If you do not delay, on some silicon it will
    // completely latch up the flash to where you need
    // to cycle power, so wait for at least
    // 6us for LVD start-up, see errata
    t0 = _CP0_GET_COUNT();
    while (_CP0_GET_COUNT() - t0 < ((6 * F_CPU) / 2 / 1000000UL));

    // magic unlock sequence
    NVMKEY = 0xAA996655;
    NVMKEY = 0x556699AA;
    NVMCONSET = NVMCON_WR;

    // Wait for WR bit to clear
    while (NVMCON & NVMCON_WR);

    // see errata, wait 500ns before writing to any NVM register
    t0 = _CP0_GET_COUNT();
    while (_CP0_GET_COUNT() - t0 < ((F_CPU / 2 / 2000000UL)));

    // Disable Flash Write/Erase operations
    NVMCONCLR = NVMCON_WREN;

    #if defined(_PCACHE)
        // restore predictive prefetching and caching, see errata
        WriteK0(K0);
        CHECONSET = PFEN;
    #endif

    // Restore Interrupts
    RestoreINT(status);

    // assert no errors
    return(! (NVMCON & (_NVMCON_WRERR_MASK | _NVMCON_LVDERR_MASK)));
}