KL25Z Comparator library

Dependents:   ComparatorIn_demo TEMT6200_demo 05_comparator_demo 05_comparator_demo ... more

KL25Z Comparator library

Comparator features

  • Operational over the entire supply range
  • Inputs may range from rail to rail
  • Programmable hysteresis control
  • Selectable interrupt on rising-edge, falling-edge, or both rising or falling edges of the comparator output
  • Selectable inversion on comparator output
  • Capability to produce a wide range of outputs such as:
    • Sampled
    • Windowed, which is ideal for certain PWM zero-crossing-detection applications
    • Digitally filtered:
      • Filter can be bypassed
      • Can be clocked via external SAMPLE signal or scaled bus clock
  • External hysteresis can be used at the same time that the output filter is used for internal functions
  • Two software selectable performance levels:
    • Shorter propagation delay at the expense of higher power
    • Low power, with longer propagation delay
  • DMA transfer support not yet implemented in this library
    • A comparison event can be selected to trigger a DMA transfer
  • Functional in all modes of operation
  • The window and filter functions are not available in the following modes:
    • Stop
    • VLPS
    • LLS
    • VLLSx

Block diagram

/media/uploads/frankvnk/kl25z_comparator_block_diagram.jpg

Introduction

This library allows us to create comparator objects between different inputs.
The comparator + and - inputs can be routed to one out of eight reference inputs (see table).
Input selection

Pin name#MUX inputCMP0Comment
PTC6000IN0CMP0_IN0
PTC7001IN1CMP0_IN1
PTC8010IN2CMP0_IN2
PTC9011IN3CMP0_IN3
PTE30100IN4CMP0_IN412-bit DAC0
PTE29101IN5CMP0_IN5
110IN61V internal Bandgap*
NC111IN7internal 6-bit DAC0
(table 1)

* Not yet implemented

Using the library

Selecting pins on initialisation
Upon initialisation, the comparator registers are set to following values:

    CMP0->CR0   = 0x00;  // Filter and digital hysteresis disabled
    CMP0->CR1   = 0x17;  // Continuous mode, high-speed compare, unfiltered output, output pin disabled
    CMP0->FPR   = 0x00;  // Filter disabled
    CMP0->SCR   = 0x06;  // Disable all interrupts and clear flags (flags are cleared by this write)
    CMP0->DACCR = 0xE0;  // DAC enabled, Vdd is 6bit reference, threshold set to 1/2 of full-scale (1.65V)

The library accepts two input parameters:
example:

ComparatorIn compi(PTC8, NC);
  • First parameter : + input pin.
  • Second parameter : - input pin.
    Every pin from the 'Pin name' column in (table 1) can be selected.

notes

  • IN6 (internal 1V bandgap reference) has no pin name and is not selectable on init.
    However, we can use the SwitchPlus and SwitchMin functions to change the corresponding input to IN6.
  • There are two special cases for the input parameters:
    • NC : Connect the internal 6-bit DAC0 to IN7.
    • PTE30 : configures PTE30 as 12-bit DAC0 output and connect to IN4.
      IMPORTANT: Make sure no external output is connected to PTE30 when you declare this pin, otherwise you WILL destroy the external device and/or the CPU.

Example
Following code demonstrates interrupt callback and polling mode.
Note: Polling the comparator this way won't always trigger the printf because of the wait() instructions (if we go above and below the threshold during the wait() time, then the polling cannot not see this change).

/***********************************************************
CODE EXAMPLE FOR AMBIENT LIGHT SENSOR ON KL25Z + Wi-Go BOARD
 ***********************************************************/
#include "ComparatorIn.h"
#include "mbed.h"

DigitalOut blinker(LED_BLUE);
DigitalOut cmpled(LED_GREEN);
DigitalOut cmp_en (PTD5);
AnalogIn cmp_lvl (PTB0);
ComparatorIn compi(PTC8, NC); // in+ = PTC8, in- = internal 6-bit DAC 

// Comparator callback functions
void cmp_rise_ISR(void)
{
    cmpled = 0;
}

void cmp_fall_ISR(void)
{
    cmpled = 1;
}

int main()
{
    cmp_en = 1;
    cmpled = 1;

    compi.rising(&cmp_rise_ISR);                // Set pointer to rising interrupt function
    compi.falling(&cmp_fall_ISR);               // Set pointer to falling interrupt function
    compi.treshold(0.5);                        // Set comparator threshold to 1.65V = 32 * 3.3V / 64

    while(1)
    {
        printf("Light sensor : %7.5f Volt\n",cmp_lvl*3.3);
        blinker = 1;
        wait(1);
        blinker = 0;
        wait(0.2);
        if (compi.status() == 0x01)
        {
            printf("*** Treshold reached : %7.5f\n",cmp_lvl*3.3);
        }
    }
}


Notes

  • When we enable the comparator interrupt, we need to declare user callback function(s) (rising and/or falling interrupt) AND initialise the function pointer(s).
    example:

compi.rising(&cmp_rise_ISR);
compi.falling(&cmp_fall_ISR);
  • Currently, following functions are not yet implemented:
    • On the fly MUX switching for + input (SwitchPlus function).
    • On the fly MUX switching for - input (SwitchMin function).
    • DMA transfer.
Committer:
frankvnk
Date:
Sun Aug 25 18:00:42 2013 +0000
Revision:
19:e6a4cd28e217
Parent:
17:048474f28d28
_fptr names were too generic. Added comparatorin_ to each name.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
frankvnk 1:ccac56d8f1cb 1 /**************************************************************************************************
frankvnk 1:ccac56d8f1cb 2 ***** *****
frankvnk 1:ccac56d8f1cb 3 ***** Name: ComparatorIn.cpp *****
frankvnk 1:ccac56d8f1cb 4 ***** Date: 05/06/2013 *****
frankvnk 1:ccac56d8f1cb 5 ***** Auth: Frank Vannieuwkerke *****
frankvnk 1:ccac56d8f1cb 6 ***** Func: library for KL25Z Comparator *****
frankvnk 1:ccac56d8f1cb 7 ***** *****
frankvnk 1:ccac56d8f1cb 8 **************************************************************************************************/
frankvnk 1:ccac56d8f1cb 9
frankvnk 0:e742ad3d7dac 10 #include "ComparatorIn.h"
frankvnk 0:e742ad3d7dac 11
frankvnk 19:e6a4cd28e217 12 void (*comparatorin_rise_fptr)(void); // Pointer to user function - called after rising IRQ assertion.
frankvnk 19:e6a4cd28e217 13 void (*comparatorin_fall_fptr)(void); // Pointer to user function - called after falling IRQ assertion.
frankvnk 19:e6a4cd28e217 14 AnalogOut *_dac12; // Pointer to AnalogOut
frankvnk 0:e742ad3d7dac 15
frankvnk 0:e742ad3d7dac 16 const PinMap ComparatorIn::PinMap_CMP[] = {
frankvnk 0:e742ad3d7dac 17 {PTC6, CMP0_IN0, 0},
frankvnk 0:e742ad3d7dac 18 {PTC7, CMP0_IN1, 0},
frankvnk 0:e742ad3d7dac 19 {PTC8, CMP0_IN2, 0},
frankvnk 0:e742ad3d7dac 20 {PTC9, CMP0_IN3, 0},
frankvnk 15:f340e0545b53 21 {PTE30, CMP0_IN4, 0}, // 12-bit DAC0
frankvnk 0:e742ad3d7dac 22 {PTE29, CMP0_IN5, 0}, // ADC0_SE4b
frankvnk 15:f340e0545b53 23 {NC, NC, 0} // Internal 6-bit DAC0
frankvnk 0:e742ad3d7dac 24 };
frankvnk 17:048474f28d28 25
frankvnk 17:048474f28d28 26
frankvnk 0:e742ad3d7dac 27 ComparatorIn::ComparatorIn(PinName pinP, PinName pinM)
frankvnk 0:e742ad3d7dac 28 {
frankvnk 19:e6a4cd28e217 29 comparatorin_rise_fptr = NULL;
frankvnk 19:e6a4cd28e217 30 comparatorin_fall_fptr = NULL;
frankvnk 0:e742ad3d7dac 31 CMPnumberP = (CMPName)pinmap_peripheral(pinP, PinMap_CMP);
frankvnk 0:e742ad3d7dac 32 if (CMPnumberP == (uint32_t)NC) // When NC, use DAC0
frankvnk 0:e742ad3d7dac 33 CMPnumberP = 0x07;
frankvnk 0:e742ad3d7dac 34 CMPnumberM = (CMPName)pinmap_peripheral(pinM, PinMap_CMP);
frankvnk 0:e742ad3d7dac 35 if (CMPnumberM == (uint32_t)NC) // When NC, use DAC0
frankvnk 0:e742ad3d7dac 36 CMPnumberM = 0x07;
frankvnk 0:e742ad3d7dac 37
frankvnk 0:e742ad3d7dac 38 SIM->SCGC4 |=SIM_SCGC4_CMP_MASK; // Enable HSCMP module clock
frankvnk 0:e742ad3d7dac 39
frankvnk 0:e742ad3d7dac 40 hscmp_clear();
frankvnk 0:e742ad3d7dac 41 CMP0->CR0 = 0x00; // Filter and digital hysteresis disabled
frankvnk 0:e742ad3d7dac 42 CMP0->CR1 = 0x17; // Continuous mode, high-speed compare, unfiltered output, output pin disabled
frankvnk 0:e742ad3d7dac 43 CMP0->FPR = 0x00; // Filter disabled
frankvnk 13:2d499824ba05 44 CMP0->SCR = 0x06; // Disable all interrupts and clear flags (flags are cleared by this write)
frankvnk 6:9b1268dd1d16 45 CMP0->DACCR = 0xE0; // DAC enabled, Vdd is 6bit reference, threshold set to 1/2 of full-scale (1.65V)
frankvnk 0:e742ad3d7dac 46 CMP0->MUXCR = (CMPnumberP << 3) | (CMPnumberM & 0x07); // P-input/M-input are ext.channels defined by CMPnumberP/CMPnumberN
frankvnk 0:e742ad3d7dac 47
frankvnk 14:875486333dc2 48 if(CMPnumberP < 6) pinmap_pinout(pinP, PinMap_CMP); // Map pins
frankvnk 14:875486333dc2 49 if(CMPnumberM < 6) pinmap_pinout(pinM, PinMap_CMP); // Map pins
frankvnk 15:f340e0545b53 50
frankvnk 15:f340e0545b53 51 if((CMPnumberP == 4) || (CMPnumberM == 4)) _dac12 = new AnalogOut (PTE30); // When PTE30 is selected, use it as 12-bit DAC
frankvnk 14:875486333dc2 52
frankvnk 14:875486333dc2 53 NVIC_SetVector(CMP0_IRQn, (uint32_t)&_cmpISR); // Set comparator ISR to _cmpISR routine
frankvnk 17:048474f28d28 54 falling(NULL); // set falling IRQ pointer to NULL
frankvnk 17:048474f28d28 55 rising(NULL); // set rising IRQ pointer to NULL
frankvnk 17:048474f28d28 56 NVIC_DisableIRQ(CMP0_IRQn); // disable CMP0 IRQ
frankvnk 0:e742ad3d7dac 57 };
frankvnk 0:e742ad3d7dac 58
frankvnk 17:048474f28d28 59 void ComparatorIn::FilterCount(unsigned char fico)
frankvnk 0:e742ad3d7dac 60 {
frankvnk 0:e742ad3d7dac 61 if((fico > 0) && (fico < 8))
frankvnk 0:e742ad3d7dac 62 {
frankvnk 0:e742ad3d7dac 63 unsigned char tmp;
frankvnk 11:c0ef9948278b 64 tmp = (CMP0->CR0 & 0x8F) | CMP_CR0_FILTER_CNT(fico); // Replace old value
frankvnk 11:c0ef9948278b 65 CMP0->CR0 = tmp; // Set filter count
frankvnk 0:e742ad3d7dac 66 }
frankvnk 0:e742ad3d7dac 67 }
frankvnk 0:e742ad3d7dac 68
frankvnk 0:e742ad3d7dac 69 void ComparatorIn::hysteresis(unsigned char hyst)
frankvnk 0:e742ad3d7dac 70 {
frankvnk 0:e742ad3d7dac 71 if(hyst < 4)
frankvnk 0:e742ad3d7dac 72 {
frankvnk 0:e742ad3d7dac 73 unsigned char tmp;
frankvnk 11:c0ef9948278b 74 tmp = (CMP0->CR0 & 0xFC) | CMP_CR0_HYSTCTR(hyst); // Replace old value
frankvnk 11:c0ef9948278b 75 CMP0->CR0 = tmp; // Set hysteresis
frankvnk 0:e742ad3d7dac 76 }
frankvnk 0:e742ad3d7dac 77 }
frankvnk 0:e742ad3d7dac 78
frankvnk 17:048474f28d28 79 void ComparatorIn::SampleMode(unsigned char samp_en)
frankvnk 0:e742ad3d7dac 80 {
frankvnk 0:e742ad3d7dac 81 if((CMP0->CR1 & CMP_CR1_WE_MASK) == 0) // Only allow change when window mode is inactive
frankvnk 0:e742ad3d7dac 82 {
frankvnk 0:e742ad3d7dac 83 if(samp_en == 1) CMP0->CR1 |= CMP_CR1_SE_MASK; // Enable
frankvnk 0:e742ad3d7dac 84 else CMP0->CR1 &= ~CMP_CR1_SE_MASK; // Disable
frankvnk 0:e742ad3d7dac 85 }
frankvnk 0:e742ad3d7dac 86 }
frankvnk 0:e742ad3d7dac 87
frankvnk 17:048474f28d28 88 void ComparatorIn::WindowMode(unsigned char win_en)
frankvnk 0:e742ad3d7dac 89 {
frankvnk 0:e742ad3d7dac 90 if((CMP0->CR1 & CMP_CR1_SE_MASK) == 0) // Only allow change when sample mode is inactive
frankvnk 0:e742ad3d7dac 91 {
frankvnk 0:e742ad3d7dac 92 if(win_en == 1) CMP0->CR1 |= CMP_CR1_WE_MASK; // Enable
frankvnk 0:e742ad3d7dac 93 else CMP0->CR1 &= ~CMP_CR1_WE_MASK; // Disable
frankvnk 0:e742ad3d7dac 94 }
frankvnk 0:e742ad3d7dac 95 }
frankvnk 0:e742ad3d7dac 96
frankvnk 17:048474f28d28 97 void ComparatorIn::TrigMode(unsigned char trig_en)
frankvnk 0:e742ad3d7dac 98 {
frankvnk 0:e742ad3d7dac 99 if(trig_en == 1) CMP0->CR1 |= CMP_CR1_TRIGM_MASK; // Enable
frankvnk 0:e742ad3d7dac 100 else CMP0->CR1 &= ~CMP_CR1_TRIGM_MASK; // Disable
frankvnk 0:e742ad3d7dac 101 }
frankvnk 0:e742ad3d7dac 102
frankvnk 17:048474f28d28 103 void ComparatorIn::PowerMode(unsigned char pmode)
frankvnk 0:e742ad3d7dac 104 {
frankvnk 0:e742ad3d7dac 105 if(pmode == 1) CMP0->CR1 |= CMP_CR1_PMODE_MASK; // Set high speed
frankvnk 0:e742ad3d7dac 106 else CMP0->CR1 &= ~CMP_CR1_PMODE_MASK; // Set low speed
frankvnk 0:e742ad3d7dac 107 }
frankvnk 0:e742ad3d7dac 108
frankvnk 0:e742ad3d7dac 109 void ComparatorIn::invert(unsigned char inv)
frankvnk 0:e742ad3d7dac 110 {
frankvnk 0:e742ad3d7dac 111 if(inv == 1) CMP0->CR1 |= CMP_CR1_INV_MASK; // Enable
frankvnk 0:e742ad3d7dac 112 else CMP0->CR1 &= ~CMP_CR1_INV_MASK; // Disable
frankvnk 0:e742ad3d7dac 113 }
frankvnk 0:e742ad3d7dac 114
frankvnk 17:048474f28d28 115 void ComparatorIn::OutputSelect(unsigned char cos)
frankvnk 0:e742ad3d7dac 116 {
frankvnk 0:e742ad3d7dac 117 if(cos == 1) CMP0->CR1 |= CMP_CR1_COS_MASK; // Enable
frankvnk 0:e742ad3d7dac 118 else CMP0->CR1 &= ~CMP_CR1_COS_MASK; // Disable
frankvnk 0:e742ad3d7dac 119 }
frankvnk 0:e742ad3d7dac 120
frankvnk 17:048474f28d28 121 void ComparatorIn::OutputPin(PinName ope)
frankvnk 0:e742ad3d7dac 122 {
frankvnk 12:0a0648bddb98 123 PinName pin_stat;
frankvnk 12:0a0648bddb98 124 pin_stat = op_status(); // Get pin status
frankvnk 12:0a0648bddb98 125 // Only change settings if new pin differs from old pin AND the correct pin is selected.
frankvnk 12:0a0648bddb98 126 if((ope != pin_stat) && ((ope == PTC0) || (ope == PTC5) || (ope == PTE0) || (ope == NC)))
frankvnk 12:0a0648bddb98 127 {
frankvnk 12:0a0648bddb98 128 if(ope == NC)
frankvnk 12:0a0648bddb98 129 {
frankvnk 12:0a0648bddb98 130 if (pin_stat != NC) op_disable(pin_stat); // disconnect current pin
frankvnk 12:0a0648bddb98 131 CMP0->CR1 &= ~CMP_CR1_OPE_MASK; // Disable comparator output pin connect
frankvnk 12:0a0648bddb98 132 }
frankvnk 12:0a0648bddb98 133 else
frankvnk 12:0a0648bddb98 134 {
frankvnk 12:0a0648bddb98 135 op_enable(ope, pin_stat); // Connect new pin
frankvnk 12:0a0648bddb98 136 CMP0->CR1 &= ~CMP_CR1_OPE_MASK; // Enable comparator output pin connect
frankvnk 12:0a0648bddb98 137 }
frankvnk 12:0a0648bddb98 138 }
frankvnk 0:e742ad3d7dac 139 }
frankvnk 0:e742ad3d7dac 140
frankvnk 0:e742ad3d7dac 141 void ComparatorIn::enable(unsigned char en)
frankvnk 0:e742ad3d7dac 142 {
frankvnk 0:e742ad3d7dac 143 if(en == 1) CMP0->CR1 |= CMP_CR1_EN_MASK; // Enable
frankvnk 0:e742ad3d7dac 144 else CMP0->CR1 &= ~CMP_CR1_EN_MASK; // Disable
frankvnk 0:e742ad3d7dac 145 }
frankvnk 0:e742ad3d7dac 146
frankvnk 17:048474f28d28 147 void ComparatorIn::FilterPeriod(unsigned char fipe)
frankvnk 0:e742ad3d7dac 148 {
frankvnk 0:e742ad3d7dac 149 CMP0->FPR = CMP_FPR_FILT_PER(fipe);
frankvnk 0:e742ad3d7dac 150 }
frankvnk 0:e742ad3d7dac 151
frankvnk 17:048474f28d28 152 void ComparatorIn::dma(unsigned char dmaen)
frankvnk 0:e742ad3d7dac 153 {
frankvnk 0:e742ad3d7dac 154 if(dmaen == 1) CMP0->SCR |= CMP_SCR_DMAEN_MASK; // Enable
frankvnk 0:e742ad3d7dac 155 else CMP0->SCR &= ~CMP_SCR_DMAEN_MASK; // Disable
frankvnk 0:e742ad3d7dac 156 }
frankvnk 0:e742ad3d7dac 157
frankvnk 0:e742ad3d7dac 158 unsigned char ComparatorIn::status(void)
frankvnk 0:e742ad3d7dac 159 {
frankvnk 0:e742ad3d7dac 160 return (CMP0->SCR & 0x01);
frankvnk 0:e742ad3d7dac 161 }
frankvnk 0:e742ad3d7dac 162
frankvnk 17:048474f28d28 163 void ComparatorIn::dac(unsigned char den)
frankvnk 0:e742ad3d7dac 164 {
frankvnk 0:e742ad3d7dac 165 if(den == 1) CMP0->DACCR |= CMP_DACCR_DACEN_MASK; // Enable
frankvnk 0:e742ad3d7dac 166 else CMP0->DACCR &= ~CMP_DACCR_DACEN_MASK; // Disable
frankvnk 0:e742ad3d7dac 167 }
frankvnk 0:e742ad3d7dac 168
frankvnk 17:048474f28d28 169 void ComparatorIn::RefSource(unsigned char res)
frankvnk 0:e742ad3d7dac 170 {
frankvnk 0:e742ad3d7dac 171 if(res == 1) CMP0->DACCR |= CMP_DACCR_VRSEL_MASK; // Enable
frankvnk 0:e742ad3d7dac 172 else CMP0->DACCR &= ~CMP_DACCR_VRSEL_MASK; // Disable
frankvnk 0:e742ad3d7dac 173 }
frankvnk 0:e742ad3d7dac 174
frankvnk 13:2d499824ba05 175 void ComparatorIn::treshold(float vo_pct)
frankvnk 0:e742ad3d7dac 176 {
frankvnk 15:f340e0545b53 177
frankvnk 15:f340e0545b53 178 if(vo_pct < 0.0) vo_pct = 0.0;
frankvnk 15:f340e0545b53 179 if(vo_pct > 1.0) vo_pct = 1.0;;
frankvnk 15:f340e0545b53 180
frankvnk 15:f340e0545b53 181 if((CMPnumberP == 7) || (CMPnumberM == 7))
frankvnk 13:2d499824ba05 182 {
frankvnk 13:2d499824ba05 183 dac6_write(vo_pct * (float)0x3F);
frankvnk 0:e742ad3d7dac 184 }
frankvnk 15:f340e0545b53 185 if((CMPnumberP == 4) || (CMPnumberM == 4))
frankvnk 15:f340e0545b53 186 {
frankvnk 15:f340e0545b53 187 _dac12->write(vo_pct);
frankvnk 15:f340e0545b53 188 }
frankvnk 0:e742ad3d7dac 189 }
frankvnk 0:e742ad3d7dac 190
frankvnk 17:048474f28d28 191 void ComparatorIn::PassThrough(unsigned char ptm)
frankvnk 0:e742ad3d7dac 192 {
frankvnk 0:e742ad3d7dac 193 if(ptm == 1) CMP0->MUXCR |= CMP_MUXCR_MSEL_MASK; // Enable
frankvnk 0:e742ad3d7dac 194 else CMP0->MUXCR &= ~CMP_MUXCR_MSEL_MASK; // Disable
frankvnk 0:e742ad3d7dac 195 }
frankvnk 0:e742ad3d7dac 196
frankvnk 17:048474f28d28 197 void ComparatorIn::SwitchPlus(unsigned char pinP)
frankvnk 0:e742ad3d7dac 198 {
frankvnk 0:e742ad3d7dac 199 }
frankvnk 0:e742ad3d7dac 200
frankvnk 17:048474f28d28 201 void ComparatorIn::SwitchMin(unsigned char pinM)
frankvnk 0:e742ad3d7dac 202 {
frankvnk 0:e742ad3d7dac 203 }
frankvnk 0:e742ad3d7dac 204
frankvnk 0:e742ad3d7dac 205 void ComparatorIn::hscmp_clear(void)
frankvnk 0:e742ad3d7dac 206 {
frankvnk 0:e742ad3d7dac 207 CMP0->CR0 = 0;
frankvnk 0:e742ad3d7dac 208 CMP0->CR1 = 0;
frankvnk 0:e742ad3d7dac 209 CMP0->FPR = 0;
frankvnk 0:e742ad3d7dac 210 CMP0->SCR = 0x06; // Clear flags if set.
frankvnk 0:e742ad3d7dac 211 CMP0->DACCR = 0;
frankvnk 0:e742ad3d7dac 212 CMP0->MUXCR = 0;
frankvnk 0:e742ad3d7dac 213 }
frankvnk 0:e742ad3d7dac 214
frankvnk 14:875486333dc2 215 void ComparatorIn::rising(void(*fptr)(void))
frankvnk 0:e742ad3d7dac 216 {
frankvnk 17:048474f28d28 217 if(fptr == NULL)
frankvnk 17:048474f28d28 218 {
frankvnk 17:048474f28d28 219 CMP0->SCR &= ~CMP_SCR_IER_MASK; // Disable rising int.
frankvnk 17:048474f28d28 220 CMP0->SCR |= CMP_SCR_CFR_MASK; // clear flag
frankvnk 19:e6a4cd28e217 221 if(comparatorin_fall_fptr == NULL)
frankvnk 17:048474f28d28 222 NVIC_DisableIRQ(CMP0_IRQn);
frankvnk 17:048474f28d28 223 }
frankvnk 17:048474f28d28 224 else
frankvnk 17:048474f28d28 225 {
frankvnk 19:e6a4cd28e217 226 comparatorin_rise_fptr = fptr;
frankvnk 17:048474f28d28 227 CMP0->SCR |= (CMP_SCR_IER_MASK | CMP_SCR_CFR_MASK); // Enable rising int. and clear flag
frankvnk 17:048474f28d28 228 NVIC_EnableIRQ(CMP0_IRQn); // enable CMP0 interrupt
frankvnk 17:048474f28d28 229 }
frankvnk 14:875486333dc2 230 }
frankvnk 17:048474f28d28 231
frankvnk 14:875486333dc2 232 void ComparatorIn::falling(void(*fptr)(void))
frankvnk 14:875486333dc2 233 {
frankvnk 17:048474f28d28 234 if(fptr == NULL)
frankvnk 17:048474f28d28 235 {
frankvnk 17:048474f28d28 236 CMP0->SCR &= ~CMP_SCR_IEF_MASK; // Disable falling int.
frankvnk 17:048474f28d28 237 CMP0->SCR |= CMP_SCR_CFF_MASK; // clear flag
frankvnk 19:e6a4cd28e217 238 if(comparatorin_rise_fptr == NULL)
frankvnk 17:048474f28d28 239 NVIC_DisableIRQ(CMP0_IRQn);
frankvnk 17:048474f28d28 240 }
frankvnk 17:048474f28d28 241 else
frankvnk 17:048474f28d28 242 {
frankvnk 19:e6a4cd28e217 243 comparatorin_fall_fptr = fptr;
frankvnk 17:048474f28d28 244 CMP0->SCR |= (CMP_SCR_IEF_MASK | CMP_SCR_CFF_MASK); // Enable falling int. and clear flag
frankvnk 17:048474f28d28 245 NVIC_EnableIRQ(CMP0_IRQn); // enable CMP0 interrupt
frankvnk 17:048474f28d28 246 }
frankvnk 0:e742ad3d7dac 247 }
frankvnk 0:e742ad3d7dac 248
frankvnk 0:e742ad3d7dac 249 void ComparatorIn::_cmpISR(void)
frankvnk 0:e742ad3d7dac 250 {
frankvnk 14:875486333dc2 251 // Interrupt flags are cleared by writing 1 to the CFx flag
frankvnk 14:875486333dc2 252 // Rising edge
frankvnk 0:e742ad3d7dac 253 if (((CMP0->SCR & CMP_SCR_IER_MASK)==CMP_SCR_IER_MASK) && ((CMP0->SCR & CMP_SCR_CFR_MASK)==CMP_SCR_CFR_MASK))
frankvnk 0:e742ad3d7dac 254 {
frankvnk 19:e6a4cd28e217 255 CMP0->SCR |= CMP_SCR_CFR_MASK; // Clear the flag
frankvnk 19:e6a4cd28e217 256 if (comparatorin_rise_fptr != NULL) comparatorin_rise_fptr(); // call user function
frankvnk 0:e742ad3d7dac 257 }
frankvnk 0:e742ad3d7dac 258
frankvnk 14:875486333dc2 259 // Falling edge
frankvnk 0:e742ad3d7dac 260 if (((CMP0->SCR & CMP_SCR_IEF_MASK)==CMP_SCR_IEF_MASK) && ((CMP0->SCR & CMP_SCR_CFF_MASK)==CMP_SCR_CFF_MASK))
frankvnk 0:e742ad3d7dac 261 {
frankvnk 19:e6a4cd28e217 262 CMP0->SCR |= CMP_SCR_CFF_MASK; // Clear the flag
frankvnk 19:e6a4cd28e217 263 if (comparatorin_fall_fptr != NULL) comparatorin_fall_fptr(); // call user function
frankvnk 12:0a0648bddb98 264 }
frankvnk 12:0a0648bddb98 265 }
frankvnk 12:0a0648bddb98 266
frankvnk 12:0a0648bddb98 267 /*
frankvnk 12:0a0648bddb98 268 IMPORTANT : Do not alter the if... sequence in op_status.
frankvnk 12:0a0648bddb98 269 We need to check if the port is active (using SIM->SCGC5) BEFORE reading PORTn->PCR[x].
frankvnk 12:0a0648bddb98 270 Reading PORTn->PCR[x] while a port is inactive will block the system.
frankvnk 12:0a0648bddb98 271 At startup, SIM->SCGC5 = 00000380h. This means only PORTA is enabled.
frankvnk 12:0a0648bddb98 272 */
frankvnk 12:0a0648bddb98 273 PinName ComparatorIn::op_status(void)
frankvnk 12:0a0648bddb98 274 {
frankvnk 12:0a0648bddb98 275 if((SIM->SCGC5 & SIM_SCGC5_PORTE_MASK) == 1)
frankvnk 12:0a0648bddb98 276 {
frankvnk 12:0a0648bddb98 277 if((PORTE->PCR[0] & PORT_PCR_MUX_MASK) == 0x500u) return(PTE0); // check if current pin = PTE0
frankvnk 0:e742ad3d7dac 278 }
frankvnk 12:0a0648bddb98 279 if((SIM->SCGC5 & SIM_SCGC5_PORTC_MASK) == 1)
frankvnk 12:0a0648bddb98 280 {
frankvnk 12:0a0648bddb98 281 if((PORTC->PCR[0] & PORT_PCR_MUX_MASK) == 0x500u) return(PTC0); // check if current pin = PTC0
frankvnk 12:0a0648bddb98 282 if((PORTC->PCR[5] & PORT_PCR_MUX_MASK) == 0x600u) return(PTC5); // check if current pin = PTC5
frankvnk 12:0a0648bddb98 283 }
frankvnk 12:0a0648bddb98 284 return(NC);
frankvnk 0:e742ad3d7dac 285 }
frankvnk 0:e742ad3d7dac 286
frankvnk 12:0a0648bddb98 287 void ComparatorIn::op_enable(PinName pen, PinName pstat)
frankvnk 12:0a0648bddb98 288 {
frankvnk 12:0a0648bddb98 289 if(pstat != NC) op_disable(pstat); // If a pin is connected - disconnect before connecting new pin
frankvnk 12:0a0648bddb98 290 switch (pen)
frankvnk 12:0a0648bddb98 291 {
frankvnk 12:0a0648bddb98 292 case PTC0:
frankvnk 12:0a0648bddb98 293 if((SIM->SCGC5 & SIM_SCGC5_PORTC_MASK) == 0) SIM->SCGC5 |= SIM_SCGC5_PORTC_MASK; // If PORTC is inactive: Enable
frankvnk 12:0a0648bddb98 294 PORTC->PCR[0] = PORT_PCR_MUX(5); // Set PTC0 mux to CMP0
frankvnk 12:0a0648bddb98 295 break;
frankvnk 12:0a0648bddb98 296 case PTC5:
frankvnk 12:0a0648bddb98 297 if((SIM->SCGC5 & SIM_SCGC5_PORTC_MASK) == 0) SIM->SCGC5 |= SIM_SCGC5_PORTC_MASK; // If PORTC is inactive: Enable
frankvnk 12:0a0648bddb98 298 PORTC->PCR[5] = PORT_PCR_MUX(6); // Set PTC5 mux to CMP0
frankvnk 12:0a0648bddb98 299 break;
frankvnk 12:0a0648bddb98 300 case PTE0:
frankvnk 12:0a0648bddb98 301 if((SIM->SCGC5 & SIM_SCGC5_PORTE_MASK) == 0) SIM->SCGC5 |= SIM_SCGC5_PORTE_MASK; // If PORTE is inactive: Enable
frankvnk 12:0a0648bddb98 302 PORTE->PCR[0] = PORT_PCR_MUX(5); // Set PTE0 mux to CMP0
frankvnk 12:0a0648bddb98 303 break;
frankvnk 12:0a0648bddb98 304 default:
frankvnk 12:0a0648bddb98 305 break;
frankvnk 12:0a0648bddb98 306 }
frankvnk 12:0a0648bddb98 307 }
frankvnk 1:ccac56d8f1cb 308
frankvnk 12:0a0648bddb98 309 void ComparatorIn::op_disable(PinName pdi)
frankvnk 12:0a0648bddb98 310 {
frankvnk 12:0a0648bddb98 311 switch (pdi)
frankvnk 12:0a0648bddb98 312 {
frankvnk 12:0a0648bddb98 313 case PTC0:
frankvnk 12:0a0648bddb98 314 PORTC->PCR[0] &= PORT_PCR_MUX(1); // Set PTC0 mux to ALT1
frankvnk 12:0a0648bddb98 315 break;
frankvnk 12:0a0648bddb98 316 case PTC5:
frankvnk 12:0a0648bddb98 317 PORTC->PCR[5] &= PORT_PCR_MUX(1); // Set PTC5 mux to ALT1
frankvnk 12:0a0648bddb98 318 break;
frankvnk 12:0a0648bddb98 319 case PTE0:
frankvnk 12:0a0648bddb98 320 PORTE->PCR[0] &= PORT_PCR_MUX(1); // Set PTE0 mux to ALT1
frankvnk 12:0a0648bddb98 321 break;
frankvnk 12:0a0648bddb98 322 default:
frankvnk 12:0a0648bddb98 323 break;
frankvnk 12:0a0648bddb98 324 }
frankvnk 12:0a0648bddb98 325 }
frankvnk 13:2d499824ba05 326
frankvnk 13:2d499824ba05 327 void ComparatorIn::dac6_write(unsigned int value)
frankvnk 13:2d499824ba05 328 {
frankvnk 13:2d499824ba05 329 unsigned int tmp;
frankvnk 13:2d499824ba05 330 value &= 0x3F; // 6-bit
frankvnk 13:2d499824ba05 331 tmp = (CMP0->DACCR & 0xC0) | value; // Replace old value
frankvnk 13:2d499824ba05 332 CMP0->DACCR = tmp; // Set Vout DAC
frankvnk 13:2d499824ba05 333 }
frankvnk 14:875486333dc2 334
frankvnk 15:f340e0545b53 335
frankvnk 17:048474f28d28 336