11 Appendix B: Code Example, Data Updates and Override

Data Updates and Override

Void __inline__ PWM_AllRegistersWrite (void)
{
// Master writes – note MPER set to MAX_PERIOD in init routine
    MPHASE = priPWMHighPhase; 
    MDC = priPWMHighDuty;
    
    AMPHASE = syncPWMHighPhase;
    AMDC = syncPWMHighDuty;
    
    PG1PER = llcPeriod;
    PG1TRIGA = priPWMLowTrigA;
    PG1TRIGB = priPWMLowTrigB;
    PG1TRIGC = phase120OffSetDaisyChain;
    PG1TRIGD = phase240OffSetDaisyChain;   

    PG2PHASE = syncPWMHighPhase;
    PG2DC = syncPWMHighDuty;
    PG2TRIGA = syncPWMLowTrigA;
    PG2TRIGB = syncPWMLowTrigB;
    PG2TRIGC = phase90OffSetDaisyChain;
        
    PG3TRIGA = PG4TRIGA = PG5TRIGA = priPWMLowTrigA;
    PG3TRIGB = PG4TRIGB = PG5TRIGB = priPWMLowTrigB;

    PG5TRIGC = phase120OffSetDaisyChain;  
    PG5TRIGD = phase240OffSetDaisyChain; 

    PG6PHASE = syncPWMHighPhase;
    PG6DC = syncPWMHighDuty;
    PG6TRIGA = syncPWMLowTrigA;
    PG6TRIGB = syncPWMLowTrigB;
    
    PG7TRIGA = PG8TRIGA = priPWMLowTrigA;
    PG7TRIGB = PG8TRIGB = priPWMLowTrigB;

    APG1TRIGA = APG2TRIGA = APG3TRIGA = APG4TRIGA = syncPWMLowTrigA;
    APG1TRIGB = APG2TRIGB = APG3TRIGB = APG4TRIGB = syncPWMLowTrigB;
}

void __attribute__ ((interrupt, no_auto_psv, context)) _T1Interrupt(void)
{
    // Simulate ADC ISR at 100 kHz
    _T1IF = 0;

    // Sweep period up and down
    if (up_down == 0) {
        ctrlOutput -= PERIOD_CHANGE;}
    else {
        ctrlOutput += PERIOD_CHANGE;}

    if (ctrlOutput >= MAX_PERIOD + 64){
        up_down = 0;
        ctrlOutput = MAX_PERIOD;}
    else if (ctrlOutput <= MIN_PERIOD){
        up_down = 1; 
        ctrlOutput = MIN_PERIOD;}

    if ((updateFlag == 0) && (PG8STATbits.UPDATE == 0)) 
    {
        priSyncDiffRising = SYNC_DIFF_RISE;  // Can be runtime configurable
        priSyncDiffFalling = SYNC_DIFF_FALL;
        llcPeriod = ctrlOutput & 0xFFFF0;
        phase120OffSetDaisyChain = (__builtin_muluu_32(llcPeriod, 1365)>>12);
        phase120OffSetDaisyChain & = 0xFFFF0; 
        phase90OffSetDaisyChain = (llcPeriod>>2) & 0xFFFF0;
        phase240OffSetDaisyChain = phase120OffSetDaisyChain<<1;
        priPWMHighPhase = DEADTIME;	   // Can be runtime configurable
        priPWMHighDuty = (llcPeriod >> 1);
        priPWMLowTrigA = priPWMHighDuty + deadTime;
        priPWMLowTrigB = llcPeriod;
        syncPWMHighPhase = DEADTIME + priSyncDiffRising;
        syncPWMHighDuty = (llcPeriod >> 1) - priSyncDiffFalling;
        syncPWMLowTrigA = priPWMLowTrigA + priSyncDiffRising;
        syncPWMLowTrigB = priPWMLowTrigB - priSyncDiffFalling;

        PWM_AllRegistersWrite();
        updateFlag = 1; // All data written, ready for PWM update - PWM8 IRS

        _PWM8IF = 0;
        _PWM8IE = 1;    // Enable PWM8 ISR for scheduling 
    }
}

void __attribute__ ((interrupt, no_auto_psv, context)) _PWM8Interrupt(void) {
    if (updateFlag  == 1) {
        PG1STATbits.UPDREQ = 1;
        APG1STATbits.UPDREQ = 1;
        updateFlag = 0;
    }

    _PWM8IE = 0;
    _PWM8IF = 0;    // Disable PWM8 ISR until next write cycle complete
}


void PrimaryOverride(void) {
    PG1IOCON2 |= 0x00300000;
    PG3IOCON2 |= 0x00300000;
    PG4IOCON2 |= 0x00300000;
    PG5IOCON2 |= 0x00300000;
    PG7IOCON2 |= 0x00300000;
    PG8IOCON2 |= 0x00300000; 
}

void SecondaryOverride(void) {
    PG2IOCON2 |= 0x00300000;
    PG6IOCON2 |= 0x00300000;
    APG1IOCON2 |= 0x00300000; 
    APG2IOCON2 |= 0x00300000; 
    APG3IOCON2 |= 0x00300000;
    APG4IOCON2 |= 0x00300000;
}

void PrimaryOverrideDisable(void) {
    PG1IOCON2 &= 0xFFCFFFFF;
    PG3IOCON2 &= 0xFFCFFFFF;
    PG4IOCON2 &= 0xFFCFFFFF;
    PG5IOCON2 &= 0xFFCFFFFF;
    PG7IOCON2 &= 0xFFCFFFFF;
    PG8IOCON2 &= 0xFFCFFFFF;
}

void SecondaryOverrideDisable(void) {
    PG2IOCON2 &= 0xFFCFFFFF;
    PG6IOCON2 &= 0xFFCFFFFF;
    APG1IOCON2 &= 0xFFCFFFFF;
    APG2IOCON2 &= 0xFFCFFFFF;
    APG3IOCON2 &= 0xFFCFFFFF;
}