void refreshDisplay(displayRGB16x32 *display) // Load image to display { uint32_t delay = 10; // Define clock pulse delay //CtrlPort &= ~(A+B+C+D+OE+CLK+STB); // Clear control pins //CtrlPort |= OE; // Transmit image to display uint8_t i; int8_t j; for(i=0; i<8; i++) // Transmit each row { // Set row address CtrlPort = (i & 1) ? (CtrlPort | A) : (CtrlPort & ~A); CtrlPort = (i & 2) ? (CtrlPort | B) : (CtrlPort & ~B); CtrlPort = (i & 4) ? (CtrlPort | C) : (CtrlPort & ~C); CtrlPort = (i & 8) ? (CtrlPort | D) : (CtrlPort & ~D); uint32_t bitmask = BIT(31); for(j=31; j>=0; j--) // Transmit each pixel in each row { if(display->redRow[i] & bitmask) DataPort_R0R1 |= R0; else DataPort_R0R1 &= ~R0; if(display->redRow[i+8] & bitmask) DataPort_R0R1 |= R1; else DataPort_R0R1 &= ~R1; if(display->greenRow[i] & bitmask) DataPort_G0 |= G0; else DataPort_G0 &= ~G0; if(display->greenRow[i+8] & bitmask) DataPort_G1 |= G1; else DataPort_G1 &= ~G1; if(display->blueRow[i] & bitmask) DataPort_B0B1 |= B0; else DataPort_B0B1 &= ~B0; if(display->blueRow[i+8] & bitmask) DataPort_B0B1 |= B1; else DataPort_B0B1 &= ~B1; // Clock pulse delayCycles(delay); CtrlPort &= ~CLK; delayCycles(delay); CtrlPort |= CLK; // Update bitmask bitmask = bitmask >> 1; } // Latch and flash row CtrlPort |= STB; // Latch data delayCycles(delay); CtrlPort &= ~STB; // Clear latch delayCycles(delay); CtrlPort &= ~OE; // Enable LED output delayCycles(500); CtrlPort |= OE; // Disable LED output } }
/** Set up the PIC32 ADC to sample from AN2 periodically using Timer3 as the * trigger. DMA is used to move the ADC result into #adc_sample_buffer. */ void initADC(void) { // Initialise DMA module and DMA channel 0. // Why use DMA? DMA transfers will continue even when interrupts are // disabled, making sampling more robust (especially against USB // activity). DMA transfers also introduce less interference into the // signal, compared to using an interrupt service handler. DMACONbits.ON = 0; // disable DMA controller asm("nop"); // just to be safe IEC1bits.DMA0IE = 0; // disable DMA channel 0 interrupt IFS1bits.DMA0IF = 0; // clear DMA channel 0 interrupt flag DMACONbits.ON = 1; // enable DMA controller DMACONbits.SUSPEND = 0; // disable DMA suspend DCH0CON = 0; DCH0CONbits.CHPRI = 3; // priority = highest DCH0ECON = 0; DCH0ECONbits.CHSIRQ = _ADC_IRQ; // start transfer on ADC interrupt DCH0ECONbits.SIRQEN = 1; // start cell transfer on IRQ DCH0INTCLR = 0x00ff00ff; // clear existing events, disable all interrupts // Initialise ADC module. AD1CON1bits.ON = 0; // turn ADC module off asm("nop"); // just to be safe // This follows section 17.4 of the PIC32 family reference manual. AD1PCFGbits.PCFG2 = 0; // set AN2 pin to analog mode TRISBbits.TRISB2 = 1; // set RB2 as input (disable digital output) TRISCbits.TRISC13 = 1; // set RC13 as input (disable digital output) TRISCbits.TRISC14 = 1; // set RC14 as input (disable digital output) AD1CHSbits.CH0SA = 2; // select AN2 as MUX A positive source AD1CHSbits.CH0NA = 0; // select AVss as MUX a negative source AD1CON1bits.FORM = 4; // output format = 32 bit integer AD1CON1bits.SSRC = 2; // use Timer3 to trigger conversions AD1CON1bits.ASAM = 1; // enable automatic sampling AD1CON2bits.VCFG = 0; // use AVdd/AVss as references AD1CON2bits.CSCNA = 0; // disable scan mode AD1CON2bits.SMPI = 0; // 1 sample per interrupt AD1CON2bits.BUFM = 0; // single buffer mode AD1CON2bits.ALTS = 0; // disable alternate mode (always use MUX A) AD1CON3bits.ADRC = 0; // derive ADC conversion clock from PBCLK // Don't need to set SAMC since ADC is not in auto-convert (continuous) // mode. //AD1CON3bits.SAMC = 12; // sample time = 12 ADC conversion clocks AD1CON3bits.ADCS = 15; // ADC conversion clock = 2.25 MHz AD1CON1bits.SIDL = 1; // discontinue operation in idle mode AD1CON1bits.CLRASAM = 0; // don't clear ASAM; overwrite buffer contents AD1CON1bits.SAMP = 0; // don't start sampling immediately AD1CON2bits.OFFCAL = 0; // disable offset calibration mode AD1CON1bits.ON = 1; // turn ADC module on IFS1bits.AD1IF = 0; // clear interrupt flag IEC1bits.AD1IE = 0; // disable interrupt delayCycles(4 * CYCLES_PER_MICROSECOND); // wait 4 microsecond for ADC to stabilise // Initialise Timer3 to trigger ADC conversions. T3CONbits.ON = 0; // turn timer off T3CONbits.SIDL = 0; // continue operation in idle mode T3CONbits.TCKPS = 0; // 1:1 prescaler T3CONbits.TGATE = 0; // disable gated time accumulation T3CONbits.SIDL = 0; // continue in idle mode TMR3 = 0; // clear count PR3 = 1500; // frequency = 48000 Hz IFS0bits.T3IF = 0; // clear interrupt flag IEC0bits.T3IE = 0; // disable timer interrupt T3CONbits.ON = 1; // turn timer on }