Subversion Repositories Code-Repo

Rev

Blame | Last modification | View Log | RSS feed

#include <xc.h>
#include "defines.h"
#include "base_CPS.h"

static CPS_DATA *cps_data_p;

void CPS_Init(CPS_DATA* data) {
    cps_data_p = data;
    for (char i = 0; i < 4; i++) {
        cps_data_p->btn_pressed[i] = 0;
        cps_data_p->btn_last_value[i] = 0;
        cps_data_p->btn_avg_value[i] = 0;
        cps_data_p->btn_pct_value[i] = 0;
    }

    /* Initialize port direction */
    CPS_0_TRIS = 1;
    CPS_1_TRIS = 1;

    /* Initialize FVR for the upper threshold (Ref+) */
    FVRCONbits.CDAFVR = 0b01; // Gain of 1x (1.024V)
    FVRCONbits.FVREN = 1; // Enable FVR module

    /* Initialize DAC for the lower threshold (Ref-) */
    DACCON0bits.DACEN = 0; // Disable DAC
    DACCON0bits.DACLPS = 0; // Negative reference source selected
    DACCON0bits.DACOE = 0; // Output not routed to DACOUT pin
    DACCON0bits.DACPSS = 0b00; // Vdd used as positive source
//    DACCON0bits.DACNSS = 0; // Vss used as negative source
    DACCON1bits.DACR = 0b00000; // Voltage output set to 0

    /* Initialize Timer 0 */
    OPTION_REGbits.TMR0CS = 0; // Clock source is FOSC/4
    OPTION_REGbits.PSA = 0; // Prescaler enabled
    OPTION_REGbits.PS = 0b111; // Prescaler of 1:256

    /* Initialize Timer 1 */
    T1CONbits.TMR1CS = 0b11; // Clock source is Capacitive Sensing Oscillator
    T1CONbits.T1CKPS = 0b00; // 1:1 Prescale value
    T1GCONbits.TMR1GE = 1; // Counting is controlled by the gate function
    T1GCONbits.T1GPOL = 1; // Gate is active high
    T1GCONbits.T1GTM = 1; // Gate toggle mode is enabled
    T1GCONbits.T1GSPM = 0; // Gate single-pulse mode is disabled
    T1GCONbits.T1GSS = 0b01; // Gate source is Timer 0 overflow
    T1CONbits.TMR1ON = 1; // Enables timer 1

    /* Initialize CPS Module */
    CPSCON0bits.CPSRM = 1; // DAC and FVR used for Vref- and Vref+
    CPSCON0bits.CPSRNG = 0b11; // Osc in high range (100uA)
    CPSCON0bits.T0XCS = 0; // Timer 0 clock runs at FOSC/4
    CPSCON1bits.CPSCH = 0b00; // Channel 0 (CPS0)
    cps_data_p->channel = 0;
    CPSCON0bits.CPSON = 1; // CPS module is enabled

    /* Initialize timer interrupts and clear timers */
    INTCONbits.TMR0IE = 1; // Timer 0 interrupt enabled
    PIE1bits.TMR1IE = 0; // Timer 1 interrupt disabled
    CPS_Reset();
}

void CPS_Timer_0_Interrupt_Handler() {
    unsigned int value = TMR1;
    long percent;

    if (value < 10) {
        return;
    }

    // Calculate percentage change
    percent = (long)cps_data_p->btn_avg_value[cps_data_p->channel]-(long)value;
    if (percent < 0)
        percent = 0;
    else {
        percent *= 100;
        percent /= cps_data_p->btn_avg_value[cps_data_p->channel];
    }

    cps_data_p->btn_last_value[cps_data_p->channel] = value;
    cps_data_p->btn_pct_value[cps_data_p->channel] = percent;

    if (percent < CPS_PCT_OFF) {
        // Calculate average
        cps_data_p->btn_avg_value[cps_data_p->channel] =
            cps_data_p->btn_avg_value[cps_data_p->channel] +
            ((long)value - (long)cps_data_p->btn_avg_value[cps_data_p->channel])
            /CPS_AVG_COUNT;
        // Set flag to indicate that button is not pressed
        cps_data_p->btn_pressed[cps_data_p->channel] = 0;
    } else if (percent > CPS_PCT_ON)
        // Set flag to indicate that button was pressed
        cps_data_p->btn_pressed[cps_data_p->channel] = 1;

    cps_data_p->channel = cps_data_p->channel + 1;
    if (cps_data_p->channel == CPS_NUM_CHANNELS)
        cps_data_p->channel = 0;
    
    CPSCON1bits.CPSCH = cps_data_p->channel;

    CPS_Reset();
}

void CPS_Reset() {
    TMR1 = 0;
    TMR0 = 0;
}

void CPS_Enable() {
    INTCONbits.TMR0IE = 1; // Timer 0 interrupt enabled
    T1CONbits.TMR1ON = 1;
    CPSCON0bits.CPSON = 1;
    CPS_Reset();
}

void CPS_Disable() {
    INTCONbits.TMR0IE = 0;
    CPSCON0bits.CPSON = 0;
    T1CONbits.TMR1ON = 0;
}