Exemplo n.º 1
0
inline void I2C_setup()
{
	// Enable I2C internal clock
	SIM_SCGC4 |= SIM_SCGC4_I2C0; // Bus 0

	// External pull-up resistor
	PORTB_PCR0 = PORT_PCR_ODE | PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(2);
	PORTB_PCR1 = PORT_PCR_ODE | PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(2);

	// SCL Frequency Divider
	// 400kHz -> 120 (0x85) @ 48 MHz F_BUS
	I2C0_F = 0x85;
	I2C0_FLT = 4;
	I2C0_C1 = I2C_C1_IICEN;
	I2C0_C2 = I2C_C2_HDRS; // High drive select

	// Enable I2C Interrupt
	NVIC_ENABLE_IRQ( IRQ_I2C0 );
}
bool PulsePositionInput::begin(uint8_t pin)
{
	uint32_t channel;
	volatile void *reg;

	if (FTM0_MOD != 0xFFFF || (FTM0_SC & 0x7F) != FTM0_SC_VALUE) {
		FTM0_SC = 0;
		FTM0_CNT = 0;
		FTM0_MOD = 0xFFFF;
		FTM0_SC = FTM0_SC_VALUE;
		#if defined(KINETISK)
		FTM0_MODE = 0;
		#endif
	}
	switch (pin) {
	  case  6: channel = 4; reg = &FTM0_C4SC; break;
	  case  9: channel = 2; reg = &FTM0_C2SC; break;
	  case 10: channel = 3; reg = &FTM0_C3SC; break;
	  case 20: channel = 5; reg = &FTM0_C5SC; break;
	  case 22: channel = 0; reg = &FTM0_C0SC; break;
	  case 23: channel = 1; reg = &FTM0_C1SC; break;
	  #if defined(KINETISK)
	  case 21: channel = 6; reg = &FTM0_C6SC; break;
	  case  5: channel = 7; reg = &FTM0_C7SC; break;
	  #endif
	  default:
		return false;
	}
	prev = 0;
	write_index = 255;
	available_flag = false;
	ftm = (struct ftm_channel_struct *)reg;
	list[channel] = this;
	channelmask |= (1<<channel);
	*portConfigRegister(pin) = PORT_PCR_MUX(4);
	CSC_CHANGE(ftm, cscEdge); // input capture & interrupt on rising edge
	NVIC_SET_PRIORITY(IRQ_FTM0, 32);
	NVIC_ENABLE_IRQ(IRQ_FTM0);
	return true;
}
void AudioInputI2S::begin(void)
{
	//block_left_1st = NULL;
	//block_right_1st = NULL;

	//pinMode(3, OUTPUT);
	//digitalWriteFast(3, HIGH);
	//delayMicroseconds(500);
	//digitalWriteFast(3, LOW);

	// TODO: should we set & clear the I2S_RCSR_SR bit here?
	AudioOutputI2S::config_i2s();

	CORE_PIN13_CONFIG = PORT_PCR_MUX(4); // pin 13, PTC5, I2S0_RXD0

	DMA_CR = 0;
	DMA_TCD1_SADDR = &I2S0_RDR0;
	DMA_TCD1_SOFF = 0;
	DMA_TCD1_ATTR = DMA_TCD_ATTR_SSIZE(1) | DMA_TCD_ATTR_DSIZE(1);
	DMA_TCD1_NBYTES_MLNO = 2;
	DMA_TCD1_SLAST = 0;
	DMA_TCD1_DADDR = i2s_rx_buffer;
	DMA_TCD1_DOFF = 2;
	DMA_TCD1_CITER_ELINKNO = sizeof(i2s_rx_buffer) / 2;
	DMA_TCD1_DLASTSGA = -sizeof(i2s_rx_buffer);
	DMA_TCD1_BITER_ELINKNO = sizeof(i2s_rx_buffer) / 2;
	DMA_TCD1_CSR = DMA_TCD_CSR_INTHALF | DMA_TCD_CSR_INTMAJOR;

	DMAMUX0_CHCFG1 = DMAMUX_DISABLE;
	DMAMUX0_CHCFG1 = DMAMUX_SOURCE_I2S0_RX | DMAMUX_ENABLE;
	update_responsibility = update_setup();
	DMA_SERQ = 1;

	// TODO: is I2S_RCSR_BCE appropriate if sync'd to transmitter clock?
	//I2S0_RCSR |= I2S_RCSR_RE | I2S_RCSR_BCE | I2S_RCSR_FRDE | I2S_RCSR_FR;
	I2S0_RCSR |= I2S_RCSR_RE | I2S_RCSR_FRDE | I2S_RCSR_FR;
	NVIC_ENABLE_IRQ(IRQ_DMA_CH1);
}
void init_servo(void)
{
	// for servo
	SIM_SCGC6 |= SIM_SCGC6_PDB;	// TODO: use bitband for atomic read-mod-write
	pinMode(12, OUTPUT);
	PDB0_MOD = 0xFFFF;
	PDB0_CNT = 0;
	PDB0_IDLY = 0;
	PDB0_SC = PDB_CONFIG;
	NVIC_ENABLE_IRQ(IRQ_PDB);
	// TODO: maybe this should be a higher priority than most
	// other interrupts (init all to some default?)
	PDB0_SC = PDB_CONFIG | PDB_SC_SWTRIG;

	//servo_active_mask = 9;
	servo_active_mask = 8;
	//servo_pin[0] = 12;
	//servo_ticks[0] = usToTicks(600);
	servo_pin[3] = 11;
	servo_ticks[3] = usToTicks(2100);
	//pinMode(12, OUTPUT);
	pinMode(11, OUTPUT);
}
Exemplo n.º 5
0
uint8_t Servo::attach(int pin, int minimum, int maximum)
{
	if (servoIndex < MAX_SERVOS) {
		pinMode(pin, OUTPUT);
		servo_pin[servoIndex] = pin;
		servo_ticks[servoIndex] = usToTicks(DEFAULT_PULSE_WIDTH);
		servo_active_mask |= (1<<servoIndex);
		min_ticks = usToTicks(minimum);
		max_ticks = usToTicks(maximum);
		if (!(SIM_SCGC6 & SIM_SCGC6_PDB)) {
			SIM_SCGC6 |= SIM_SCGC6_PDB; // TODO: use bitband for atomic bitset
			PDB0_MOD = 0xFFFF;
			PDB0_CNT = 0;
			PDB0_IDLY = 0;
			PDB0_SC = PDB_CONFIG;
			// TODO: maybe this should be a higher priority than most
			// other interrupts (init all to some default?)
			PDB0_SC = PDB_CONFIG | PDB_SC_SWTRIG;
		}
		NVIC_ENABLE_IRQ(IRQ_PDB);
	}
	return servoIndex;
}
Exemplo n.º 6
0
bool PulsePositionInput::begin(uint8_t pin)
{
	uint32_t channel;
	volatile void *reg;

	if (FTM0_MOD != 0xFFFF || FTM0_SC != (FTM_SC_CLKS(1) | FTM_SC_PS(0))) {
		FTM0_SC = 0;
		FTM0_CNT = 0;
		FTM0_MOD = 0xFFFF;
		FTM0_SC = FTM_SC_CLKS(1) | FTM_SC_PS(0);
		FTM0_MODE = 0;
	}
	switch (pin) {
	  case  5: channel = 7; reg = &FTM0_C7SC; break;
	  case  6: channel = 4; reg = &FTM0_C4SC; break;
	  case  9: channel = 2; reg = &FTM0_C2SC; break;
	  case 10: channel = 3; reg = &FTM0_C3SC; break;
	  case 20: channel = 5; reg = &FTM0_C5SC; break;
	  case 21: channel = 6; reg = &FTM0_C6SC; break;
	  case 22: channel = 0; reg = &FTM0_C0SC; break;
	  case 23: channel = 1; reg = &FTM0_C1SC; break;
	  default:
		return false;
	}
	prev = 0;
	write_index = 255;
	available_flag = false;
	ftm = (struct ftm_channel_struct *)reg;
	ftm->csc = cscEdge; // input capture & interrupt on rising edge
	list[channel] = this;
	channelmask |= (1<<channel);
	*portConfigRegister(pin) = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE;
	NVIC_SET_PRIORITY(IRQ_FTM0, 32);
	NVIC_ENABLE_IRQ(IRQ_FTM0);
	return true;
}
Exemplo n.º 7
0
void HAL_adc_init() {
  analog_init();
  while (ADC0_SC3 & ADC_SC3_CAL) {}; // Wait for calibration to finish
  while (ADC1_SC3 & ADC_SC3_CAL) {}; // Wait for calibration to finish
  NVIC_ENABLE_IRQ(IRQ_FTM1);
}
Exemplo n.º 8
0
void CIO::startInt()
{
  // Initialise the DAC
  SIM_SCGC2 |= SIM_SCGC2_DAC0;
  DAC0_C0    = DAC_C0_DACEN | DAC_C0_DACRFS;                          // 3.3V VDDA is DACREF_2

  // Initialise ADC0
  SIM_SCGC6 |= SIM_SCGC6_ADC0;
  ADC0_CFG1  = ADC_CFG1_ADIV(1) | ADC_CFG1_ADICLK(1) |                // Single-ended 12 bits, long sample time
               ADC_CFG1_MODE(1) | ADC_CFG1_ADLSMP;
  ADC0_CFG2  = ADC_CFG2_MUXSEL | ADC_CFG2_ADLSTS(2);                  // Select channels ADxxxb
  ADC0_SC2   = ADC_SC2_REFSEL(0) | ADC_SC2_ADTRG;                     // Voltage ref external, hardware trigger
  ADC0_SC3   = ADC_SC3_AVGE | ADC_SC3_AVGS(0);                        // Enable averaging, 4 samples

  ADC0_SC3  |= ADC_SC3_CAL;
  while (ADC0_SC3 & ADC_SC3_CAL)                                      // Wait for calibration
    ;

  uint16_t sum0 = ADC0_CLPS + ADC0_CLP4 + ADC0_CLP3 +                 // Plus side gain
                  ADC0_CLP2 + ADC0_CLP1 + ADC0_CLP0;
  sum0 = (sum0 / 2U) | 0x8000U;
  ADC0_PG    = sum0;

  ADC0_SC1A  = ADC_SC1_AIEN | PIN_ADC;                                // Enable ADC interrupt, use A0
  NVIC_ENABLE_IRQ(IRQ_ADC0);

#if defined(SEND_RSSI_DATA)
  // Initialise ADC1
  SIM_SCGC3 |= SIM_SCGC3_ADC1;
  ADC1_CFG1  = ADC_CFG1_ADIV(1) | ADC_CFG1_ADICLK(1) |                // Single-ended 12 bits, long sample time
               ADC_CFG1_MODE(1) | ADC_CFG1_ADLSMP;
  ADC1_CFG2  = ADC_CFG2_MUXSEL | ADC_CFG2_ADLSTS(2);                  // Select channels ADxxxb
  ADC1_SC2   = ADC_SC2_REFSEL(0);                                     // Voltage ref external, software trigger
  ADC1_SC3   = ADC_SC3_AVGE | ADC_SC3_AVGS(0);                        // Enable averaging, 4 samples

  ADC1_SC3  |= ADC_SC3_CAL;
  while (ADC1_SC3 & ADC_SC3_CAL)                                      // Wait for calibration
    ;

  uint16_t sum1 = ADC1_CLPS + ADC1_CLP4 + ADC1_CLP3 +                 // Plus side gain
                  ADC1_CLP2 + ADC1_CLP1 + ADC1_CLP0;
  sum1 = (sum1 / 2U) | 0x8000U;
  ADC1_PG    = sum1;
#endif

#if defined(EXTERNAL_OSC)
  // Set ADC0 to trigger from the LPTMR at 24 kHz
  SIM_SOPT7   = SIM_SOPT7_ADC0ALTTRGEN |                              // Enable ADC0 alternate trigger
                SIM_SOPT7_ADC0TRGSEL(14);                             // Trigger ADC0 by LPTMR0

  CORE_PIN13_CONFIG = PORT_PCR_MUX(3);

  SIM_SCGC5  |= SIM_SCGC5_LPTIMER;                                    // Enable Low Power Timer Access
  LPTMR0_CSR  = 0;                                                    // Disable
  LPTMR0_PSR  = LPTMR_PSR_PBYP;                                       // Bypass prescaler/filter
  LPTMR0_CMR  = (EXTERNAL_OSC / 24000) - 1;                           // Frequency divided by CMR + 1
  LPTMR0_CSR  = LPTMR_CSR_TPS(2) |                                    // Pin: 0=CMP0, 1=xtal, 2=pin13
                LPTMR_CSR_TMS;                                        // Mode Select, 0=timer, 1=counter
  LPTMR0_CSR |= LPTMR_CSR_TEN;                                        // Enable
#else
  // Setup PDB for ADC0 at 24 kHz
  SIM_SCGC6  |= SIM_SCGC6_PDB;                                        // Enable PDB clock
  PDB0_MOD    = (F_BUS / 24000) - 1;                                  // Timer period - 1
  PDB0_IDLY   = 0;                                                    // Interrupt delay
  PDB0_CH0C1  = PDB_CHnC1_TOS | PDB_CHnC1_EN;                         // Enable pre-trigger for ADC0
  PDB0_SC     = PDB_SC_TRGSEL(15) | PDB_SC_PDBEN |                    // SW trigger, enable interrupts, continuous mode
                PDB_SC_PDBIE | PDB_SC_CONT | PDB_SC_LDOK;             // No prescaling
  PDB0_SC    |= PDB_SC_SWTRIG;                                        // Software trigger (reset and restart counter)
#endif

  digitalWrite(PIN_PTT, m_pttInvert ? HIGH : LOW);
  digitalWrite(PIN_COSLED, LOW);
  digitalWrite(PIN_LED,    HIGH);
}
Exemplo n.º 9
0
void FlexCAN::begin (uint32_t baud, const CAN_filter_t &mask, uint8_t txAlt, uint8_t rxAlt)
{
    // set up the pins

    if (flexcanBase == FLEXCAN0_BASE) {
        dbg_println ("Begin setup of CAN0");

#if defined(__MK66FX1M0__) || defined(__MK64FX512__)
        //  3=PTA12=CAN0_TX,  4=PTA13=CAN0_RX (default)
        // 29=PTB18=CAN0_TX, 30=PTB19=CAN0_RX (alternative)

        if (txAlt == 1)
            CORE_PIN29_CONFIG = PORT_PCR_MUX(2);
        else
            CORE_PIN3_CONFIG = PORT_PCR_MUX(2);

        // | PORT_PCR_PE | PORT_PCR_PS;

        if (rxAlt == 1)
            CORE_PIN30_CONFIG = PORT_PCR_MUX(2);
        else
            CORE_PIN4_CONFIG = PORT_PCR_MUX(2);
#else
        //  3=PTA12=CAN0_TX,  4=PTA13=CAN0_RX (default)
        // 32=PTB18=CAN0_TX, 25=PTB19=CAN0_RX (alternative)

        if (txAlt == 1)
            CORE_PIN32_CONFIG = PORT_PCR_MUX(2);
        else
            CORE_PIN3_CONFIG = PORT_PCR_MUX(2);

        // | PORT_PCR_PE | PORT_PCR_PS;

        if (rxAlt == 1)
            CORE_PIN25_CONFIG = PORT_PCR_MUX(2);
        else
            CORE_PIN4_CONFIG = PORT_PCR_MUX(2);
#endif
    }
#if defined(INCLUDE_FLEXCAN_CAN1)
    else if (flexcanBase == FLEXCAN1_BASE) {
        dbg_println("Begin setup of CAN1");

        // 33=PTE24=CAN1_TX, 34=PTE25=CAN1_RX (default)
        // NOTE: Alternative CAN1 pins are not broken out on Teensy 3.6

        CORE_PIN33_CONFIG = PORT_PCR_MUX(2);
        CORE_PIN34_CONFIG = PORT_PCR_MUX(2);// | PORT_PCR_PE | PORT_PCR_PS;
    }
#endif

    // select clock source 16MHz xtal

    OSC0_CR |= OSC_ERCLKEN;

    if (flexcanBase == FLEXCAN0_BASE) {
        SIM_SCGC6 |=  SIM_SCGC6_FLEXCAN0;
#if defined(INCLUDE_FLEXCAN_CAN1)
    } else if (flexcanBase == FLEXCAN1_BASE) {
        SIM_SCGC3 |=  SIM_SCGC3_FLEXCAN1;
#endif
    }

    FLEXCANb_CTRL1(flexcanBase) &= ~FLEXCAN_CTRL_CLK_SRC;

    // enable CAN

    FLEXCANb_MCR (flexcanBase) |=  FLEXCAN_MCR_FRZ;
    FLEXCANb_MCR (flexcanBase) &= ~FLEXCAN_MCR_MDIS;

    while (FLEXCANb_MCR(flexcanBase) & FLEXCAN_MCR_LPM_ACK)
        ;

    // soft reset

    FLEXCANb_MCR (flexcanBase) ^=  FLEXCAN_MCR_SOFT_RST;

    while (FLEXCANb_MCR (flexcanBase) & FLEXCAN_MCR_SOFT_RST)
        ;

    // wait for freeze ack

    while (!(FLEXCANb_MCR(flexcanBase) & FLEXCAN_MCR_FRZ_ACK))
        ;

    // disable self-reception

    FLEXCANb_MCR (flexcanBase) |= FLEXCAN_MCR_SRX_DIS;

    /*
      now using a system that tries to automatically generate a viable baud setting.
      Bear these things in mind:
      - The master clock is 16Mhz
      - You can freely divide it by anything from 1 to 256
      - There is always a start bit (+1)
      - The rest (prop, seg1, seg2) are specified 1 less than their actual value (aka +1)
      - This gives the low end bit timing as 5 (1 + 1 + 2 + 1) and the high end 25 (1 + 8 + 8 + 8)
      A worked example: 16Mhz clock, divisor = 19+1, bit values add up to 16 = 16Mhz / 20 / 16 = 50k baud
    */

    // have to find a divisor that ends up as close to the target baud as possible while keeping the end result between 5 and 25

    uint32_t divisor = 0;
    uint32_t bestDivisor = 0;
    uint32_t result = 16000000 / baud / (divisor + 1);
    int error = baud - (16000000 / (result * (divisor + 1)));
    int bestError = error;

    while (result > 5) {
        divisor++;
        result = 16000000 / baud / (divisor + 1);

        if (result <= 25) {
            error = baud - (16000000 / (result * (divisor + 1)));

            if (error < 0)
                error *= -1;

            // if this error is better than we've ever seen then use it - it's the best option

            if (error < bestError) {
                bestError = error;
                bestDivisor = divisor;
            }

            // If this is equal to a previously good option then
            // switch to it but only if the bit time result was in the middle of the range
            // this biases the output to use the middle of the range all things being equal
            // Otherwise it might try to use a higher divisor and smaller values for prop, seg1, seg2
            // and that's not necessarily the best idea.

            if ((error == bestError) && (result > 11) && (result < 19)) {
                bestError = error;
                bestDivisor = divisor;
            }
        }
    }

    divisor = bestDivisor;
    result = 16000000 / baud / (divisor + 1);

    if ((result < 5) || (result > 25) || (bestError > 300)) {
        Serial.println ("Abort in CAN begin. Couldn't find a suitable baud config!");
        return;
    }

    result -= 5; // the bitTimingTable is offset by 5 since there was no reason to store bit timings for invalid numbers
    uint8_t propSeg = bitTimingTable[result][0];
    uint8_t pSeg1   = bitTimingTable[result][1];
    uint8_t pSeg2   = bitTimingTable[result][2];

    // baud rate debug information

    dbg_println ("Bit time values:");
    dbg_print ("Prop = ");
    dbg_println (propSeg + 1);
    dbg_print ("Seg1 = ");
    dbg_println (pSeg1 + 1);
    dbg_print ("Seg2 = ");
    dbg_println (pSeg2 + 1);
    dbg_print ("Divisor = ");
    dbg_println (divisor + 1);

    FLEXCANb_CTRL1 (flexcanBase) = (FLEXCAN_CTRL_PROPSEG(propSeg) | FLEXCAN_CTRL_RJW(1) | FLEXCAN_CTRL_ERR_MSK |
                                    FLEXCAN_CTRL_PSEG1(pSeg1) | FLEXCAN_CTRL_PSEG2(pSeg2) | FLEXCAN_CTRL_PRESDIV(divisor));

    // enable per-mailbox filtering

    FLEXCANb_MCR(flexcanBase) |= FLEXCAN_MCR_IRMQ;

    // now have to set mask and filter for all the Rx mailboxes or they won't receive anything by default.

    for (uint8_t c = 0; c < NUM_MAILBOXES - numTxMailboxes; c++) {
        setMask (0, c);
        setFilter (mask, c);
    }

    // start the CAN

    FLEXCANb_MCR(flexcanBase) &= ~(FLEXCAN_MCR_HALT);

    // wait till exit of freeze mode

    while (FLEXCANb_MCR(flexcanBase) & FLEXCAN_MCR_FRZ_ACK)
        ;

    // wait till ready

    while (FLEXCANb_MCR(flexcanBase) & FLEXCAN_MCR_NOT_RDY)
        ;

    setNumTxBoxes (2);

#if defined(__MK20DX256__)
    NVIC_SET_PRIORITY (IRQ_CAN_MESSAGE, IRQ_PRIORITY);
    NVIC_ENABLE_IRQ (IRQ_CAN_MESSAGE);
#elif defined(__MK64FX512__)
    NVIC_SET_PRIORITY (IRQ_CAN0_MESSAGE, IRQ_PRIORITY);
    NVIC_ENABLE_IRQ (IRQ_CAN0_MESSAGE);
#elif defined(__MK66FX1M0__)
    if (flexcanBase == FLEXCAN0_BASE) {
        NVIC_SET_PRIORITY (IRQ_CAN0_MESSAGE, IRQ_PRIORITY);
        NVIC_ENABLE_IRQ (IRQ_CAN0_MESSAGE);
    } else {
        NVIC_SET_PRIORITY (IRQ_CAN1_MESSAGE, IRQ_PRIORITY);
        NVIC_ENABLE_IRQ (IRQ_CAN1_MESSAGE);
    }
#endif

    // enable interrupt masks for all 16 mailboxes

    FLEXCANb_IMASK1 (flexcanBase) = 0xFFFF;

    dbg_println ("CAN initialized properly");
}
Exemplo n.º 10
0
bool PulsePositionOutput::begin(uint8_t txPin, uint8_t framePin)
{
    uint32_t channel;
    volatile void *reg;

    if (FTM0_MOD != 0xFFFF || FTM0_SC != (FTM_SC_CLKS(1) | FTM_SC_PS(0))) {
        FTM0_SC = 0;
        FTM0_CNT = 0;
        FTM0_MOD = 0xFFFF;
        FTM0_SC = FTM_SC_CLKS(1) | FTM_SC_PS(0);
        FTM0_MODE = 0;
    }
    switch (txPin) {
    case  5:
        channel = 7;
        reg = &FTM0_C7SC;
        break;
    case  6:
        channel = 4;
        reg = &FTM0_C4SC;
        break;
    case  9:
        channel = 2;
        reg = &FTM0_C2SC;
        break;
    case 10:
        channel = 3;
        reg = &FTM0_C3SC;
        break;
    case 20:
        channel = 5;
        reg = &FTM0_C5SC;
        break;
    case 21:
        channel = 6;
        reg = &FTM0_C6SC;
        break;
    case 22:
        channel = 0;
        reg = &FTM0_C0SC;
        break;
    case 23:
        channel = 1;
        reg = &FTM0_C1SC;
        break;
    default:
        return false;
    }
    if (framePin < NUM_DIGITAL_PINS) {
        framePinReg = portOutputRegister(framePin);
        pinMode(framePin, OUTPUT);
        *framePinReg = 1;
    } else {
        framePinReg = NULL;
    }
    state = 0;
    current_channel = 0;
    total_channels = 0;
    ftm = (struct ftm_channel_struct *)reg;
    ftm->cv = 200;
    ftm->csc = cscSet; // set on compare match & interrupt
    list[channel] = this;
    channelmask |= (1<<channel);
    *portConfigRegister(txPin) = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE;
    NVIC_SET_PRIORITY(IRQ_FTM0, 32);
    NVIC_ENABLE_IRQ(IRQ_FTM0);
    return true;
}
Exemplo n.º 11
0
// ------------------------------------------------------------------------------------------------------
// Initialize I2C - initializes I2C as Master or address range Slave
// return: none
// parameters:
//      mode = I2C_MASTER, I2C_SLAVE
//      address1 = 1st 7bit address for specifying Slave address range (ignored for Master mode)
//      address2 = 2nd 7bit address for specifying Slave address range (ignored for Master mode)
//      pins = Wire: I2C_PINS_18_19, I2C_PINS_16_17 / Wire1: I2C_PINS_29_30, I2C_PINS_26_31
//      pullup = I2C_PULLUP_EXT, I2C_PULLUP_INT
//      rate = I2C_RATE_100, I2C_RATE_200, I2C_RATE_300, I2C_RATE_400, I2C_RATE_600, I2C_RATE_800, I2C_RATE_1000,
//             I2C_RATE_1200, I2C_RATE_1500, I2C_RATE_2000, I2C_RATE_2400
//
void i2c_t3::begin_(struct i2cStruct* i2c, uint8_t bus, i2c_mode mode, uint8_t address1, uint8_t address2, i2c_pins pins, i2c_pullup pullup, i2c_rate rate)
{
    // Enable I2C internal clock
    if(bus == 0)
        SIM_SCGC4 |= SIM_SCGC4_I2C0;
    #if I2C_BUS_NUM >= 2
        if(bus == 1)
            SIM_SCGC4 |= SIM_SCGC4_I2C1;
    #endif

    i2c->currentMode = mode; // Set mode
    i2c->currentStatus = I2C_WAITING; // reset status

    // Set Master/Slave address (zeroed in Master to prevent accidental Rx when setup is changed dynamically)
    if(i2c->currentMode == I2C_MASTER)
    {
        *(i2c->C2) = I2C_C2_HDRS; // Set high drive select
        *(i2c->A1) = 0;
        *(i2c->RA) = 0;
    }
    else
    {
        *(i2c->C2) = (address2) ? (I2C_C2_HDRS|I2C_C2_RMEN) // Set high drive select and range-match enable
                                : I2C_C2_HDRS;              // Set high drive select
        // set Slave address, if two addresses are given, setup range and put lower address in A1, higher in RA
        *(i2c->A1) = (address2) ? ((address1 < address2) ? (address1<<1) : (address2<<1))
                                : (address1<<1);
        *(i2c->RA) = (address2) ? ((address1 < address2) ? (address2<<1) : (address1<<1))
                                : 0;
    }

    // Setup pins and options (note: does not "unset" unused pins if dynamically changed, must be done elsewhere)
    // As noted in original TwoWire.cpp, internal pullup is strong (about 190 ohms), but it can work if other
    // devices on bus have strong enough pulldown devices.
    uint32_t pinConfig0 = (pullup == I2C_PULLUP_EXT) ? (PORT_PCR_MUX(2)|PORT_PCR_ODE|PORT_PCR_SRE|PORT_PCR_DSE)
                                                     : (PORT_PCR_MUX(2)|PORT_PCR_PE|PORT_PCR_PS);
    #if I2C_BUS_NUM >= 2
        uint32_t pinConfig1 = (pullup == I2C_PULLUP_EXT) ? (PORT_PCR_MUX(6)|PORT_PCR_ODE|PORT_PCR_SRE|PORT_PCR_DSE)
                                                         : (PORT_PCR_MUX(6)|PORT_PCR_PE|PORT_PCR_PS);
    #endif

    // The I2C interfaces are associated with the pins as follows:
    // I2C0 : I2C_PINS_18_19, I2C_PINS_16_17
    // I2C1 : I2C_PINS_29_30, I2C_PINS_26_31
    //
    // If pins are given an impossible value (eg. I2C0 with I2C_PINS_26_31) then the default pins will be
    // used, which for I2C0 is I2C_PINS_18_19, and for I2C1 is I2C_PINS_29_30
    //
    if(bus == 0)
    {
        if(pins == I2C_PINS_16_17)
        {
            i2c->currentPins = I2C_PINS_16_17;
            CORE_PIN16_CONFIG = pinConfig0;
            CORE_PIN17_CONFIG = pinConfig0;
        }
        else
        {
            i2c->currentPins = I2C_PINS_18_19;
            CORE_PIN18_CONFIG = pinConfig0;
            CORE_PIN19_CONFIG = pinConfig0;
        }
    }
    #if I2C_BUS_NUM >= 2
        if(bus == 1)
        {
            if(pins == I2C_PINS_26_31)
            {
                i2c->currentPins = I2C_PINS_26_31;
                CORE_PIN26_CONFIG = pinConfig1;
                CORE_PIN31_CONFIG = pinConfig1;
            }
            else
            {
                i2c->currentPins = I2C_PINS_29_30;
                CORE_PIN29_CONFIG = pinConfig0;
                CORE_PIN30_CONFIG = pinConfig0;
            }
        }
    #endif

    // Set rate and filter
    #if F_BUS == 48000000
        switch(rate)                                   // Freq  SCL Div
        {                                              // ----  -------
        case I2C_RATE_50:   *(i2c->F) = 0x2F; break;   // 50k     960
        case I2C_RATE_100:  *(i2c->F) = 0x27; break;   // 100k    480
        case I2C_RATE_200:  *(i2c->F) = 0x1F; break;   // 200k    240
        case I2C_RATE_300:  *(i2c->F) = 0x1D; break;   // 300k    160
        case I2C_RATE_400:  *(i2c->F) = 0x85; break;   // 400k    120
        case I2C_RATE_600:  *(i2c->F) = 0x14; break;   // 600k     80
        case I2C_RATE_800:  *(i2c->F) = 0x45; break;   // 800k     60
        case I2C_RATE_1000: *(i2c->F) = 0x0D; break;   // 1.0M     48
        case I2C_RATE_1200: *(i2c->F) = 0x0B; break;   // 1.2M     40
        case I2C_RATE_1500: *(i2c->F) = 0x09; break;   // 1.5M     32
        case I2C_RATE_2000: *(i2c->F) = 0x02; break;   // 2.0M     24
        case I2C_RATE_2400: *(i2c->F) = 0x00; break;   // 2.4M     20
        default:            *(i2c->F) = 0x27; break;   // 100k    480 (defaults to slowest)
        }
        *(i2c->FLT) = 4;
    #elif F_BUS == 24000000
        switch(rate)                                   // Freq  SCL Div
        {                                              // ----  -------
        case I2C_RATE_50:   *(i2c->F) = 0x27; break;   // 50k     480
        case I2C_RATE_100:  *(i2c->F) = 0x1F; break;   // 100k    240
        case I2C_RATE_200:  *(i2c->F) = 0x85; break;   // 200k    120
        case I2C_RATE_300:  *(i2c->F) = 0x14; break;   // 300k     80
        case I2C_RATE_400:  *(i2c->F) = 0x45; break;   // 400k     60
        case I2C_RATE_600:  *(i2c->F) = 0x0B; break;   // 600k     40
        case I2C_RATE_800:  *(i2c->F) = 0x05; break;   // 800k     30
        case I2C_RATE_1000: *(i2c->F) = 0x02; break;   // 1.0M     24
        case I2C_RATE_1200: *(i2c->F) = 0x00; break;   // 1.2M     20
        default:            *(i2c->F) = 0x1F; break;   // 100k    240 (defaults to slowest)
        }
        *(i2c->FLT) = 2;
    #else
        #error "F_BUS must be 48 MHz or 24 MHz"
    #endif

    // Set config registers
    if(i2c->currentMode == I2C_MASTER)
        *(i2c->C1) = I2C_C1_IICEN; // Master - enable I2C (hold in Rx mode, intr disabled)
    else
        *(i2c->C1) = I2C_C1_IICEN|I2C_C1_IICIE; // Slave - enable I2C and interrupts

    // Nested Vec Interrupt Ctrl - enable I2C interrupt
    if(bus == 0)
    {
        NVIC_ENABLE_IRQ(IRQ_I2C0);
        I2C0_INTR_FLAG_INIT; // init I2C0 interrupt flag if used
    }
    #if I2C_BUS_NUM >= 2
        if(bus == 1)
        {
            NVIC_ENABLE_IRQ(IRQ_I2C1);
            I2C1_INTR_FLAG_INIT; // init I2C1 interrupt flag if used
        }
    #endif

    #ifdef I2C_DEBUG
        if(!Serial) Serial.begin(115200);
        i2cDebugTimer.begin(printI2CDebug, 500); // 500us period, 2kHz timer
    #endif
}
Exemplo n.º 12
0
/*******************************************************************************
 *  Enable Driver
 *******************************************************************************/
void SnoozeCompare::enableDriver( void ) {
    
    if ( mode == RUN_LP ) { return; }
    if ( mode == VLPW || mode == VLPS ) {
        IRQ_NUMBER_t IRQ_CMP;
        switch (pin) {
            case 11:
                IRQ_CMP = IRQ_CMP0;
                break;
#if defined(KINETISK)
            case 9:
                IRQ_CMP = IRQ_CMP1;
                break;
            case 4:
                IRQ_CMP = IRQ_CMP2;
                break;
#endif
            default:
                IRQ_CMP = IRQ_CMP;
                return;
        }
        return_priority = NVIC_GET_PRIORITY( IRQ_CMP );//get current priority
        
        int priority = nvic_execution_priority( );// get current priority
        // if running from handler mode set priority higher than current handler
        priority = ( priority < 256 ) && ( ( priority - 16 ) > 0 ) ? priority - 16 : 128;
        NVIC_SET_PRIORITY( IRQ_CMP, priority );//set priority to new level
        __disable_irq( );
        return_cmp_irq = _VectorsRam[IRQ_CMP+16];// save prev isr
        attachInterruptVector( IRQ_CMP, wakeupIsr );
        __enable_irq( );
    }
    
    if ( SIM_SCGC4 & SIM_SCGC4_CMP ) SIM_SCGC4_clock_active = true;
    else SIM_SCGC4 |= SIM_SCGC4_CMP;
    
    CR0 = *cmpx_cr0;
    CR1 = *cmpx_cr1;
    SCR = *cmpx_scr;
    FPR = *cmpx_fpr;
    MUXCR = *cmpx_muxcr;
    DACCR = *cmpx_daccr;
    
    uint8_t _pin = 0;
    *cmpx_cr0 = 0;
    *cmpx_cr1 = 0;
    *cmpx_scr = 0;
    
#if defined(__MKL26Z64__) || defined(__MK66FX1M0__)
    if ( SIM_SCGC5 & SIM_SCGC5_LPTIMER ) SIM_SCGC5_clock_active = true;
    else SIM_SCGC5 |= SIM_SCGC5_LPTIMER;
    PSR = LPTMR0_PSR;
    CMR = LPTMR0_CMR;
    CSR = LPTMR0_CSR;
#endif
    
    if ( pin == 11 ) {
        if ( mode >= LLS ) llwu_configure_modules_mask( LLWU_CMP0_MOD );
        return_core_pin_config[0] = CORE_PIN11_CONFIG;
        CORE_PIN11_CONFIG = PORT_PCR_MUX( 0 );
        _pin = 0x00;
    }
    else if ( pin == 4 ) {
#if defined(KINETISK)
        if ( mode >= LLS ) llwu_configure_modules_mask( LLWU_CMP2_MOD );
        return_core_pin_config[1] = CORE_PIN4_CONFIG;
        CORE_PIN4_CONFIG = PORT_PCR_MUX( 0 );
        _pin = 0x01;
#else
        return;
#endif
    }
    else if ( pin == 9 ) {
#if defined(KINETISK)
        if ( mode >= LLS ) llwu_configure_modules_mask( LLWU_CMP1_MOD );
        return_core_pin_config[2] = CORE_PIN9_CONFIG;
        CORE_PIN9_CONFIG = PORT_PCR_MUX( 0 );
        _pin = 0x01;
#else
        return;
#endif
    }
    // save if isr is already enabled and enable isr if not
    if ( mode == VLPW || mode == VLPS ) {
        IRQ_NUMBER_t IRQ_CMP;
        switch (pin) {
            case 11:
                IRQ_CMP = IRQ_CMP0;
                break;
#if defined(KINETISK)
            case 9:
                IRQ_CMP = IRQ_CMP1;
                break;
            case 4:
                IRQ_CMP = IRQ_CMP2;
                break;
#endif
            default:
                IRQ_CMP = IRQ_CMP;
                return;
        }
        return_isr_enabled = NVIC_IS_ENABLED( IRQ_CMP );
        if ( return_isr_enabled == 0 ) NVIC_ENABLE_IRQ( IRQ_CMP );
    }
    
    // setup compare
    *cmpx_cr0 = CMP_CR0_FILTER_CNT( 0x07 );
    
    if ( type == CHANGE ) *cmpx_scr = CMP_SCR_CFF | CMP_SCR_CFR | CMP_SCR_IEF | CMP_SCR_IER;
    else if ( type == RISING || type == HIGH ) *cmpx_scr = CMP_SCR_CFF | CMP_SCR_CFR | CMP_SCR_IER;
    else if ( type == FALLING || type == LOW ) *cmpx_scr = CMP_SCR_CFF | CMP_SCR_CFR | CMP_SCR_IEF;
    else return;
    
    uint8_t tap = ( threshold_crossing/0.0515625 ) - 1;
    *cmpx_fpr = 0x00;
    *cmpx_muxcr = CMP_MUXCR_MSEL( 0x07 ) | CMP_MUXCR_PSEL( _pin );
    *cmpx_daccr = CMP_DACCR_DACEN | CMP_DACCR_VRSEL | CMP_DACCR_VOSEL( tap );
    
#if defined(__MKL26Z64__) || defined(__MK66FX1M0__)
    // compare needs lptmr to operate in low power with LC, 3.6
    *cmpx_cr1 = CMP_CR1_EN | CMP_CR1_TRIGM;
    SIM_SCGC5 |= SIM_SCGC5_LPTIMER;
    LPTMR0_CSR = 0;
    LPTMR0_PSR = LPTMR_PSR_PBYP | LPTMR_PSR_PCS( LPTMR_LPO );//LPO Clock
    LPTMR0_CMR = 1;
    LPTMR0_CSR = LPTMR_CSR_TEN | LPTMR_CSR_TCF;
#else
    *cmpx_cr1 = CMP_CR1_EN;
#endif
}
Exemplo n.º 13
0
void i2c_setup()
{
	for ( uint8_t ch = ISSI_I2C_FirstBus_define; ch < ISSI_I2C_Buses_define + ISSI_I2C_FirstBus_define; ch++ )
	{
#if defined(_kinetis_)
		volatile uint8_t *I2C_F   = (uint8_t*)(&I2C0_F) + i2c_offset[ch];
		volatile uint8_t *I2C_FLT = (uint8_t*)(&I2C0_FLT) + i2c_offset[ch];
		volatile uint8_t *I2C_C1  = (uint8_t*)(&I2C0_C1) + i2c_offset[ch];
		volatile uint8_t *I2C_C2  = (uint8_t*)(&I2C0_C2) + i2c_offset[ch];

		switch ( ch )
		{
		case 0:
			// Enable I2C internal clock
			SIM_SCGC4 |= SIM_SCGC4_I2C0; // Bus 0

			// External pull-up resistor
			PORTB_PCR0 = PORT_PCR_ODE | PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(2);
			PORTB_PCR1 = PORT_PCR_ODE | PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(2);

			break;

	#if defined(_kii_v2_)
		case 1:
			// Enable I2C internal clock
			SIM_SCGC4 |= SIM_SCGC4_I2C1; // Bus 1

			// External pull-up resistor
			PORTC_PCR10 = PORT_PCR_ODE | PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(2);
			PORTC_PCR11 = PORT_PCR_ODE | PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(2);

			break;
	#endif
		}

		// SCL Frequency Divider
	#if ISSI_Chip_31FL3731_define == 1 && defined(_kii_v1_)
		// 0x53 -> 48 MHz / (2 * 72) = 333.333 kBaud
		// 0x40 => mul(2)
		// 0x13 => ICR(30)
		*I2C_F = 0x53;
		*I2C_FLT = 0x05;
	#elif ISSI_Chip_31FL3731_define == 1 && defined(_kii_v2_)
		// 0x4E -> 36 MHz / (2 * 56) = 321.428 kBaud
		// 0x40 => mul(2)
		// 0x0E => ICR(56)
		*I2C_F = 0x4E;
		*I2C_FLT = 0x04;
	#elif ISSI_Chip_31FL3732_define == 1 || ISSI_Chip_31FL3733_define == 1 || ISSI_Chip_31FL3736_define == 1
		/*
		// Works
		// 0x84 -> 36 MHz / (4 * 28) = 321.428 kBaud
		// 0x80 => mul(4)
		// 0x04 => ICR(28)
		*I2C_F = 0x84;
		*I2C_FLT = 0x02;

		// Also works, 80 fps, no errors (flicker?)
		// 0x0C -> 36 MHz / (1 * 44) = 818.181 kBaud
		// 0x00 => mul(1)
		// 0x0C => ICR(44)
		*I2C_F = 0x0C;
		*I2C_FLT = 0x02; // Glitch protection, reduce if you see bus errors
		*/

		// Also works, 86 fps, no errors, using frame delay of 50 us
		// 0x40 -> 36 MHz / (2 * 20) = 900 kBaud
		// 0x40 => mul(2)
		// 0x00 => ICR(20)
		*I2C_F = 0x40;
		*I2C_FLT = 0x02;
	#endif
		*I2C_C1 = I2C_C1_IICEN;
		*I2C_C2 = I2C_C2_HDRS; // High drive select

		switch ( ch )
		{
		case 0:
			// Enable I2C Interrupt
			NVIC_ENABLE_IRQ( IRQ_I2C0 );

			// Set priority below USB, but not too low to maintain performance
			NVIC_SET_PRIORITY( IRQ_PIT_CH0, I2C_Priority_define );
			break;

	#if defined(_kii_v2_)
		case 1:

			// Enable I2C Interrupt
			NVIC_ENABLE_IRQ( IRQ_I2C1 );

			// Set priority below USB, but not too low to maintain performance
			NVIC_SET_PRIORITY( IRQ_PIT_CH1, I2C_Priority_define );
			break;
	#endif
		}

#elif defined(_sam_)

#if ISSI_Chip_31FL3731_define == 1
#define BAUD 400000
#define CK 1
#elif ISSI_Chip_31FL3732_define == 1 || ISSI_Chip_31FL3733_define == 1 || ISSI_Chip_31FL3736_define == 1
#define BAUD 800000
#define CK 0
#endif

		switch ( ch )
		{
		case 0:
			// Enable Peripheral / Disable PIO
			PIOA->PIO_PDR = (1 << 3) | (1 << 4);
			// Enable i2c clock
			PMC->PMC_PCER0 = (1 << ID_TWI0);
			break;
		case 1:
			MATRIX->CCFG_SYSIO |= CCFG_SYSIO_SYSIO4 | CCFG_SYSIO_SYSIO5; // Switch PB4 from TDI to GPIO
			PIOB->PIO_PDR = (1 << 4) | (1 << 5);
			PMC->PMC_PCER0 = (1 << ID_TWI1);
			break;
		}

		Twi *twi_dev = twi_devs[ch];
		uint16_t div = (F_CPU/BAUD - 4) / (2<<CK);

		// Set clock
		twi_dev->TWI_CWGR = TWI_CWGR_CLDIV(div) + TWI_CWGR_CHDIV(div) + TWI_CWGR_CKDIV(CK);

		// Enable master mode
		twi_dev->TWI_CR = TWI_CR_MSDIS | TWI_CR_SVDIS;
		twi_dev->TWI_CR = TWI_CR_MSEN;

		switch ( ch )
		{
		case 0:
			NVIC_SetPriority(TWI0_IRQn, I2C_Priority_define);
			NVIC_EnableIRQ(TWI0_IRQn);
			break;
		case 1:
			NVIC_SetPriority(TWI1_IRQn, I2C_Priority_define);
			NVIC_EnableIRQ(TWI1_IRQn);
			break;
		}

#endif
	}
}
void AudioInputAnalog::begin(unsigned int pin)
{
	uint32_t i, sum=0;

	// pin must be 0 to 13 (for A0 to A13)
	// or 14 to 23 for digital pin numbers A0-A9
	// or 34 to 37 corresponding to A10-A13
	if (pin > 23 && !(pin >= 34 && pin <= 37)) return;

	//pinMode(2, OUTPUT);
	//pinMode(3, OUTPUT);
	//digitalWriteFast(3, HIGH);
	//delayMicroseconds(500);
	//digitalWriteFast(3, LOW);

	// Configure the ADC and run at least one software-triggered
	// conversion.  This completes the self calibration stuff and
	// leaves the ADC in a state that's mostly ready to use
	analogReadRes(16);
	analogReference(INTERNAL); // range 0 to 1.2 volts
	//analogReference(DEFAULT); // range 0 to 3.3 volts
	analogReadAveraging(8);
	// Actually, do many normal reads, to start with a nice DC level
	for (i=0; i < 1024; i++) {
		sum += analogRead(pin);
	}
	dc_average = sum >> 10;

	// testing only, enable adc interrupt
	//ADC0_SC1A |= ADC_SC1_AIEN;
	//while ((ADC0_SC1A & ADC_SC1_COCO) == 0) ; // wait
	//NVIC_ENABLE_IRQ(IRQ_ADC0);

	// set the programmable delay block to trigger the ADC at 44.1 kHz
	SIM_SCGC6 |= SIM_SCGC6_PDB;
	PDB0_MOD = PDB_PERIOD;
	PDB0_SC = PDB_CONFIG | PDB_SC_LDOK;
	PDB0_SC = PDB_CONFIG | PDB_SC_SWTRIG;
	PDB0_CH0C1 = 0x0101;

	// enable the ADC for hardware trigger and DMA
	ADC0_SC2 |= ADC_SC2_ADTRG | ADC_SC2_DMAEN;

	// set up a DMA channel to store the ADC data
	SIM_SCGC7 |= SIM_SCGC7_DMA;
	SIM_SCGC6 |= SIM_SCGC6_DMAMUX;
	DMA_CR = 0;
	DMA_TCD2_SADDR = &ADC0_RA;
	DMA_TCD2_SOFF = 0;
	DMA_TCD2_ATTR = DMA_TCD_ATTR_SSIZE(1) | DMA_TCD_ATTR_DSIZE(1);
	DMA_TCD2_NBYTES_MLNO = 2;
	DMA_TCD2_SLAST = 0;
	DMA_TCD2_DADDR = analog_rx_buffer;
	DMA_TCD2_DOFF = 2;
	DMA_TCD2_CITER_ELINKNO = sizeof(analog_rx_buffer) / 2;
	DMA_TCD2_DLASTSGA = -sizeof(analog_rx_buffer);
	DMA_TCD2_BITER_ELINKNO = sizeof(analog_rx_buffer) / 2;
	DMA_TCD2_CSR = DMA_TCD_CSR_INTHALF | DMA_TCD_CSR_INTMAJOR;
	DMAMUX0_CHCFG2 = DMAMUX_DISABLE;
	DMAMUX0_CHCFG2 = DMAMUX_SOURCE_ADC0 | DMAMUX_ENABLE;
	update_responsibility = update_setup();
	DMA_SERQ = 2;
	NVIC_ENABLE_IRQ(IRQ_DMA_CH2);
}
Exemplo n.º 15
0
// Setup connection to other side
// - Only supports a single slave and master
// - If USB has been initiallized at this point, this side is the master
// - If both sides assert master, flash error leds
void Connect_setup( uint8_t master )
{
	// Indication that UARTs are not ready
	uarts_configured = 0;

	// Register Connect CLI dictionary
	CLI_registerDictionary( uartConnectCLIDict, uartConnectCLIDictName );

	// Check if master
	Connect_master = master;
	if ( Connect_master )
		Connect_id = 0; // 0x00 is always the master Id

	// UART0 setup
	// UART1 setup
	// Setup the the UART interface for keyboard data input
	SIM_SCGC4 |= SIM_SCGC4_UART0; // Disable clock gating
	SIM_SCGC4 |= SIM_SCGC4_UART1; // Disable clock gating

	// Pin Setup for UART0 / UART1
	PORTA_PCR1 = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(2); // RX Pin
	PORTA_PCR2 = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(2); // TX Pin
	PORTE_PCR0 = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(3); // RX Pin
	PORTE_PCR1 = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3); // TX Pin

	// Baud Rate setting
	UART0_BDH = (uint8_t)(Connect_baud >> 8);
	UART0_BDL = (uint8_t)Connect_baud;
	UART0_C4  = Connect_baudFine;
	UART1_BDH = (uint8_t)(Connect_baud >> 8);
	UART1_BDL = (uint8_t)Connect_baud;
	UART1_C4  = Connect_baudFine;

	// 8 bit, Even Parity, Idle Character bit after stop
	// NOTE: For 8 bit with Parity you must enable 9 bit transmission (pg. 1065)
	//       You only need to use UART0_D for 8 bit reading/writing though
	// UART_C1_M UART_C1_PE UART_C1_PT UART_C1_ILT
	UART0_C1 = UART_C1_M | UART_C1_PE | UART_C1_ILT;
	UART1_C1 = UART_C1_M | UART_C1_PE | UART_C1_ILT;

	// Only using Tx Fifos
	UART0_PFIFO = UART_PFIFO_TXFE;
	UART1_PFIFO = UART_PFIFO_TXFE;

	// Setup DMA clocks
	SIM_SCGC6 |= SIM_SCGC6_DMAMUX;
	SIM_SCGC7 |= SIM_SCGC7_DMA;

	// Start with channels disabled first
	DMAMUX0_CHCFG0 = 0;
	DMAMUX0_CHCFG1 = 0;

	// Configure DMA channels
	//DMA_DSR_BCR0 |= DMA_DSR_BCR_DONE_MASK; // TODO What's this?
	DMA_TCD0_CSR = 0;
	DMA_TCD1_CSR = 0;

	// Default control register
	DMA_CR = 0;

	// DMA Priority
	DMA_DCHPRI0 = 0; // Ch 0, priority 0
	DMA_DCHPRI1 = 1; // ch 1, priority 1

	// Clear error interrupts
	DMA_EEI = 0;

	// Setup TCD
	DMA_TCD0_SADDR = (uint32_t*)&UART0_D;
	DMA_TCD1_SADDR = (uint32_t*)&UART1_D;
	DMA_TCD0_SOFF = 0;
	DMA_TCD1_SOFF = 0;

	// No modulo, 8-bit transfer size
	DMA_TCD0_ATTR = DMA_TCD_ATTR_SMOD(0) | DMA_TCD_ATTR_SSIZE(0) | DMA_TCD_ATTR_DMOD(0) | DMA_TCD_ATTR_DSIZE(0);
	DMA_TCD1_ATTR = DMA_TCD_ATTR_SMOD(0) | DMA_TCD_ATTR_SSIZE(0) | DMA_TCD_ATTR_DMOD(0) | DMA_TCD_ATTR_DSIZE(0);

	// One byte transferred at a time
	DMA_TCD0_NBYTES_MLNO = 1;
	DMA_TCD1_NBYTES_MLNO = 1;

	// Source address does not change
	DMA_TCD0_SLAST = 0;
	DMA_TCD1_SLAST = 0;

	// Destination buffer
	DMA_TCD0_DADDR = (uint32_t*)uart_rx_buf[0].buffer;
	DMA_TCD1_DADDR = (uint32_t*)uart_rx_buf[1].buffer;

	// Incoming byte, increment by 1 in the rx buffer
	DMA_TCD0_DOFF = 1;
	DMA_TCD1_DOFF = 1;

	// Single major loop, must be the same value
	DMA_TCD0_CITER_ELINKNO = UART_Buffer_Size;
	DMA_TCD1_CITER_ELINKNO = UART_Buffer_Size;
	DMA_TCD0_BITER_ELINKNO = UART_Buffer_Size;
	DMA_TCD1_BITER_ELINKNO = UART_Buffer_Size;

	// Reset buffer when full
	DMA_TCD0_DLASTSGA = -( UART_Buffer_Size );
	DMA_TCD1_DLASTSGA = -( UART_Buffer_Size );

	// Enable DMA channels
	DMA_ERQ |= DMA_ERQ_ERQ0 | DMA_ERQ_ERQ1;

	// Setup DMA channel routing
	DMAMUX0_CHCFG0 = DMAMUX_ENABLE | DMAMUX_SOURCE_UART0_RX;
	DMAMUX0_CHCFG1 = DMAMUX_ENABLE | DMAMUX_SOURCE_UART1_RX;

	// Enable DMA requests (requires Rx interrupts)
	UART0_C5 = UART_C5_RDMAS;
	UART1_C5 = UART_C5_RDMAS;

	// TX Enabled, RX Enabled, RX Interrupt Enabled
	UART0_C2 = UART_C2_TE | UART_C2_RE | UART_C2_RIE;
	UART1_C2 = UART_C2_TE | UART_C2_RE | UART_C2_RIE;

	// Add interrupts to the vector table
	NVIC_ENABLE_IRQ( IRQ_UART0_STATUS );
	NVIC_ENABLE_IRQ( IRQ_UART1_STATUS );

	// UARTs are now ready to go
	uarts_configured = 1;

	// Reset the state of the UART variables
	Connect_reset();
}
Exemplo n.º 16
0
/*******************************************************************************
 *  Enable digital interrupt and configure the pin
 *******************************************************************************/
void SnoozeDigital::enableDriver( void ) {
    if ( mode == RUN_LP ) { return; }
#if defined(KINETISK)
    uint64_t _pin = pin;
    isr_pin = pin;
    if ( mode == VLPW || mode == VLPS ) {

        return_isr_a_enabled = NVIC_IS_ENABLED( IRQ_PORTA );
        return_isr_b_enabled = NVIC_IS_ENABLED( IRQ_PORTB );
        return_isr_c_enabled = NVIC_IS_ENABLED( IRQ_PORTC );
        return_isr_d_enabled = NVIC_IS_ENABLED( IRQ_PORTD );
        return_isr_e_enabled = NVIC_IS_ENABLED( IRQ_PORTE );
        NVIC_DISABLE_IRQ(IRQ_PORTA);
        NVIC_DISABLE_IRQ(IRQ_PORTB);
        NVIC_DISABLE_IRQ(IRQ_PORTC);
        NVIC_DISABLE_IRQ(IRQ_PORTD);
        NVIC_DISABLE_IRQ(IRQ_PORTE);
        NVIC_CLEAR_PENDING(IRQ_PORTA);
        NVIC_CLEAR_PENDING(IRQ_PORTB);
        NVIC_CLEAR_PENDING(IRQ_PORTC);
        NVIC_CLEAR_PENDING(IRQ_PORTD);
        NVIC_CLEAR_PENDING(IRQ_PORTE);
        
        int priority = nvic_execution_priority( );// get current priority
        // if running from interrupt set priority higher than current interrupt
        priority = ( priority < 256 ) && ( ( priority - 16 ) > 0 ) ? priority - 16 : 128;
        return_priority_a = NVIC_GET_PRIORITY( IRQ_PORTA );//get current priority
        return_priority_b = NVIC_GET_PRIORITY( IRQ_PORTB );//get current priority
        return_priority_c = NVIC_GET_PRIORITY( IRQ_PORTC );//get current priority
        return_priority_d = NVIC_GET_PRIORITY( IRQ_PORTD );//get current priority
        return_priority_e = NVIC_GET_PRIORITY( IRQ_PORTE );//get current priority
        NVIC_SET_PRIORITY( IRQ_PORTA, priority );//set priority to new level
        NVIC_SET_PRIORITY( IRQ_PORTB, priority );//set priority to new level
        NVIC_SET_PRIORITY( IRQ_PORTC, priority );//set priority to new level
        NVIC_SET_PRIORITY( IRQ_PORTD, priority );//set priority to new level
        NVIC_SET_PRIORITY( IRQ_PORTE, priority );//set priority to new level
        
        __disable_irq( );
        return_porta_irq = _VectorsRam[IRQ_PORTA+16];// save prev isr handler
        return_portb_irq = _VectorsRam[IRQ_PORTB+16];// save prev isr handler
        return_portc_irq = _VectorsRam[IRQ_PORTC+16];// save prev isr handler
        return_portd_irq = _VectorsRam[IRQ_PORTD+16];// save prev isr handler
        return_porte_irq = _VectorsRam[IRQ_PORTE+16];// save prev isr handler
        attachInterruptVector( IRQ_PORTA, isr );// set snooze digA isr
        attachInterruptVector( IRQ_PORTB, isr );// set snooze digB isr
        attachInterruptVector( IRQ_PORTC, isr );// set snooze digC isr
        attachInterruptVector( IRQ_PORTD, isr );// set snooze digD isr
        attachInterruptVector( IRQ_PORTE, isr );// set snooze digE isr
        __enable_irq( );
        
        NVIC_ENABLE_IRQ( IRQ_PORTA );
        NVIC_ENABLE_IRQ( IRQ_PORTB );
        NVIC_ENABLE_IRQ( IRQ_PORTC );
        NVIC_ENABLE_IRQ( IRQ_PORTD );
        NVIC_ENABLE_IRQ( IRQ_PORTE );
    }
    _pin = pin;
    while ( __builtin_popcountll( _pin ) ) {
        uint32_t pinNumber  = 63 - __builtin_clzll( _pin );// get pin
        
        if ( pinNumber > 33 ) break;
        
        uint32_t pin_mode = irqType[pinNumber] >> 4;// get type
        uint32_t pin_type = irqType[pinNumber] & 0x0F;// get mode
        
        volatile uint32_t *config;
        config = portConfigRegister( pinNumber );
        return_core_pin_config[pinNumber] = *config;
        
        if ( pin_mode == INPUT || pin_mode == INPUT_PULLUP ) {// setup pin mode/type/interrupt
            *portModeRegister( pinNumber ) = 0;
            if ( pin_mode == INPUT ) *config = PORT_PCR_MUX( 1 );
            else *config = PORT_PCR_MUX( 1 ) | PORT_PCR_PE | PORT_PCR_PS;// pullup
            if ( mode == VLPW || mode == VLPS ) {
                attachDigitalInterrupt( pinNumber, pin_type );// set pin interrupt
            }
            else {
                llwu_configure_pin_mask( pinNumber, mode );
            }
        } else {
            //pinMode( pinNumber, pin_mode );
            //digitalWriteFast( pinNumber, pin_type );
        }
        _pin &= ~( ( uint64_t )1 << pinNumber );// remove pin from list
    }
#elif defined(KINETISL)
    uint32_t _pin = pin;
    isr_pin = pin;
    if ( mode == VLPW || mode == VLPS ) {// if using sleep must setup pin interrupt to wake
        return_isr_a_enabled  = NVIC_IS_ENABLED( IRQ_PORTA );
        return_isr_cd_enabled = NVIC_IS_ENABLED( IRQ_PORTCD );
        NVIC_DISABLE_IRQ(IRQ_PORTA);
        NVIC_DISABLE_IRQ(IRQ_PORTCD);
        NVIC_CLEAR_PENDING(IRQ_PORTA);
        NVIC_CLEAR_PENDING(IRQ_PORTCD);
        int priority = nvic_execution_priority( );// get current priority
        // if running from interrupt set priority higher than current interrupt
        priority = ( priority < 256 ) && ( ( priority - 16 ) > 0 ) ? priority - 16 : 128;
        return_priority_a = NVIC_GET_PRIORITY( IRQ_PORTA );//get current priority
        return_priority_cd = NVIC_GET_PRIORITY( IRQ_PORTCD );//get current priority
        NVIC_SET_PRIORITY( IRQ_PORTA, priority );//set priority to new level
        NVIC_SET_PRIORITY( IRQ_PORTCD, priority );//set priority to new level
        __disable_irq( );
        return_porta_irq = _VectorsRam[IRQ_PORTA+16];// save prev isr handler
        return_portcd_irq = _VectorsRam[IRQ_PORTCD+16];// save prev isr handler
        attachInterruptVector( IRQ_PORTA, isr );// set snooze isr
        attachInterruptVector( IRQ_PORTCD, isr );// set snooze isr
        __enable_irq( );
        NVIC_ENABLE_IRQ( IRQ_PORTA );
        NVIC_ENABLE_IRQ( IRQ_PORTCD );
    }
    _pin = pin;
    while ( __builtin_popcount( _pin ) ) {
        uint32_t pinNumber  = 31 - __builtin_clz( _pin );// get pin
        
        if ( pinNumber > 33 ) break;
        
        uint32_t pin_mode = irqType[pinNumber] >> 4;// get type
        uint32_t pin_type = irqType[pinNumber] & 0x0F;// get mode
        
        volatile uint32_t *config;
        config = portConfigRegister( pinNumber );
        return_core_pin_config[pinNumber] = *config;
        
        if ( pin_mode == INPUT || pin_mode == INPUT_PULLUP ) {// setup pin mode/type/interrupt
            *portModeRegister( pinNumber ) &= ~digitalPinToBitMask( pinNumber ); // TODO: atomic
            if ( pin_mode == INPUT ) *config = PORT_PCR_MUX( 1 );
            else *config = PORT_PCR_MUX( 1 ) | PORT_PCR_PE | PORT_PCR_PS;// pullup
            if ( pin_mode == VLPW || pin_mode == VLPS ) {
               attachDigitalInterrupt( pinNumber, pin_type );// set pin interrupt
            }
            else {
                llwu_configure_pin_mask( pinNumber, pin_mode );
            }
        } else {
            //pinMode( pinNumber, pin_mode );
            //digitalWriteFast( pinNumber, pin_type );
        }
        _pin &= ~( ( uint32_t )1 << pinNumber );// remove pin from list
    }
#endif
}
Exemplo n.º 17
0
void OctoWS2811::begin(void)
{
    uint32_t frequency;


    // set up the buffers
    memset(frameBuffer[0], 0, bufSize);
    memset(frameBuffer[1], 0, bufSize);

    // configure the 8 output pins
    GPIOD_PCOR = 0xFF;
    pinMode(2, OUTPUT);	// strip #1
    pinMode(14, OUTPUT);	// strip #2
    pinMode(7, OUTPUT);	// strip #3
    pinMode(8, OUTPUT);	// strip #4
    pinMode(6, OUTPUT);	// strip #5
    pinMode(20, OUTPUT);	// strip #6
    pinMode(21, OUTPUT);	// strip #7
    pinMode(5, OUTPUT);	// strip #8

#ifdef TWOPORT
#ifdef C8SYNC //don't use pin 15-16 loopback, use something else. You still pretty much need to use pin16 as it has FTM1_CH0 muxed on it. Instead of B0 you could also use A12 (see datasheet)
    GPIOC_PCOR = 0xFF;
    pinMode(28, OUTPUT);	// C8(pin28) -> B0 for sync instead of C0-B0 to free up C0 for an extra LED strip.
#else
    //reserve C0 for pwm (this is default setup of the Octo2811 buffer board, but you can't use C0 for strip output so you only get 15 usable channels)
    GPIOC_PCOR = 0xFE;
#endif
    pinMode(22, OUTPUT);	// PC1 strip #9
    pinMode(23, OUTPUT);	// PC2 strip #10
    pinMode(9, OUTPUT);	// PC3 strip #11
    pinMode(10, OUTPUT);	// PC4 strip #12
    pinMode(13, OUTPUT);	// PC5 strip #13
    pinMode(11, OUTPUT);	// PC6 strip #14
    pinMode(12, OUTPUT);	// PC7 strip #15
#endif

#ifdef DEBUGSYNC
    pinMode(0, OUTPUT);	// B16 sync for scope testing
#endif

    // create the two waveforms for WS2811 low and high bits
    frequency = 800000;
    analogWriteResolution(8);
    analogWriteFrequency(3, frequency);
    analogWriteFrequency(4, frequency);
    analogWrite(3, WS2811_TIMING_T0H);
    analogWrite(4, WS2811_TIMING_T1H);

#ifdef C8SYNCxxxxx
    // Optionally use A12 (pin 3) instead of B0 -  triggers DMA(port B) on rising edge (configure for pin 3's waveform)
#else
    // pin 16 (b0) is FTM1_CH0, triggers DMA(port B) on rising edge (configure mux to output pin 3's waveform)
    CORE_PIN16_CONFIG = PORT_PCR_IRQC(1)|PORT_PCR_MUX(3);
    //pin35 (B0) , mux to FTM1_CH0  IRQC0001 = DMA on rising edge
    pinMode(3, INPUT_PULLUP); // pin 3 (A12, configured by the AnalogWrite(3..) above is no longer needed for PWM so set as input or whatever you like
#endif

#ifdef C8SYNC
    // pin 28 (C8) triggers DMA(port C) on falling edge of low duty waveform
    // pin 28 and 25 must be connected by the user: 25 is output, 28 is input
    pinMode(28, INPUT); //c8
    //PTC8 input,  IRQC0010 = DMA on rising edge
    CORE_PIN28_CONFIG = PORT_PCR_IRQC(2)|PORT_PCR_MUX(1);
#else
    // pin 15 (C0) triggers DMA(port C) on falling edge of low duty waveform
    // pin 15 and 16 must be connected by the user: 16 is output, 15 is input
    pinMode(15, INPUT); //c0
    //pin43 = PTC0 input,  IRQC0010 = DMA on rising edge
    CORE_PIN15_CONFIG = PORT_PCR_IRQC(2)|PORT_PCR_MUX(1);
#endif

    // pin 4 triggers DMA(port A) on falling edge of high duty waveform
    //pin29 = (A13) mux to FTM1_CH1 IRQC0010=DMA on falling edge
    CORE_PIN4_CONFIG = PORT_PCR_IRQC(2)|PORT_PCR_MUX(3);

    // enable clocks to the DMA controller and DMAMUX
    SIM_SCGC7 |= SIM_SCGC7_DMA;
    SIM_SCGC6 |= SIM_SCGC6_DMAMUX;
    DMA_CR = 0;
    DMA_ERQ = 0;

    // DMA channel #1 sets WS2811 high at the beginning of each cycle
#ifndef TWOPORT
    //original octo2811 8-channel DMA setup
    DMA_TCD1_SADDR = &ones;
    DMA_TCD1_SOFF = 0;
    DMA_TCD1_ATTR = DMA_TCD_ATTR_SSIZE(0) | DMA_TCD_ATTR_DSIZE(0);
    DMA_TCD1_NBYTES_MLNO = 1;
    DMA_TCD1_SLAST = 0;
    DMA_TCD1_DADDR = &GPIOD_PSOR;
    DMA_TCD1_DOFF = 0;
    DMA_TCD1_CITER_ELINKNO = bufSize;
    DMA_TCD1_DLASTSGA = 0;
    DMA_TCD1_CSR = DMA_TCD_CSR_DREQ;
    DMA_TCD1_BITER_ELINKNO = bufSize;

    // DMA channel #2 writes the pixel data at 20% of the cycle
    DMA_TCD2_SADDR = frameBuffer[1];
    DMA_TCD2_SOFF = 1;
    DMA_TCD2_ATTR = DMA_TCD_ATTR_SSIZE(0) | DMA_TCD_ATTR_DSIZE(0);
    DMA_TCD2_NBYTES_MLNO = 1;
    DMA_TCD2_SLAST = -bufSize;
    DMA_TCD2_DADDR = &GPIOD_PDOR;
    DMA_TCD2_DOFF = 0;
    DMA_TCD2_CITER_ELINKNO = bufSize;
    DMA_TCD2_DLASTSGA = 0;
    DMA_TCD2_CSR = DMA_TCD_CSR_DREQ;
    DMA_TCD2_BITER_ELINKNO = bufSize;

    // DMA channel #3 clear all the pins low at 48% of the cycle
    DMA_TCD3_SADDR = &ones;
    DMA_TCD3_SOFF = 0;
    DMA_TCD3_ATTR = DMA_TCD_ATTR_SSIZE(0) | DMA_TCD_ATTR_DSIZE(0);
    DMA_TCD3_NBYTES_MLNO = 1;
    DMA_TCD3_SLAST = 0;
    DMA_TCD3_DADDR = &GPIOD_PCOR;
    DMA_TCD3_DOFF = 0;
    DMA_TCD3_CITER_ELINKNO = bufSize;
    DMA_TCD3_DLASTSGA = 0;
    DMA_TCD3_CSR = DMA_TCD_CSR_DREQ | DMA_TCD_CSR_INTMAJOR;
    DMA_TCD3_BITER_ELINKNO = bufSize;
#else
    //DrTune's 16-channel DMA setup

//0x40 byte address gap between sequential ports (a,b,c,d)
#define PORT_SPACING 0x40  /*between ports C and D */
#define MLOFFYES  (1+1) // 2 byte tranfers per minor loop (port C then D)
#define FREEZE_DEST_ADDR_BITS 7 /*force dest address to alternate between ports C+D */

    DMA_CR = (1<<7); //EMLM minor loop enabled;

    //write port C and D in a minor loop
    DMA_TCD1_SADDR = &ones;
    DMA_TCD1_SOFF = 0;
    DMA_TCD1_ATTR = DMA_TCD_ATTR_SSIZE(0) | DMA_TCD_ATTR_DSIZE(0) | (FREEZE_DEST_ADDR_BITS<<3);
    DMA_TCD1_NBYTES_MLOFFYES = MLOFFYES;
    DMA_TCD1_SLAST = 0;
    DMA_TCD1_DADDR = &GPIOC_PSOR;
    DMA_TCD1_DOFF = PORT_SPACING;
    DMA_TCD1_CITER_ELINKNO = bufSize/2;
    DMA_TCD1_DLASTSGA = 0;
    DMA_TCD1_CSR = DMA_TCD_CSR_DREQ;
    DMA_TCD1_BITER_ELINKNO = bufSize/2;

    // DMA channel #2 writes the pixel data at 20% of the cycle
    DMA_TCD2_SADDR = frameBuffer[1];
    DMA_TCD2_SOFF = 1;
    DMA_TCD2_ATTR = DMA_TCD_ATTR_SSIZE(0) | DMA_TCD_ATTR_DSIZE(0) | (FREEZE_DEST_ADDR_BITS<<3);;
    DMA_TCD2_NBYTES_MLOFFYES = MLOFFYES;
    DMA_TCD2_SLAST = -bufSize;
    DMA_TCD2_DADDR = &GPIOC_PDOR;
    DMA_TCD2_DOFF = PORT_SPACING;
    DMA_TCD2_CITER_ELINKNO = bufSize/2;
    DMA_TCD2_DLASTSGA = 0;
    DMA_TCD2_CSR = DMA_TCD_CSR_DREQ;
    DMA_TCD2_BITER_ELINKNO = bufSize/2;

    // DMA channel #3 clear all the pins low at 48% of the cycle
    DMA_TCD3_SADDR = &ones;
    DMA_TCD3_SOFF = 0;
    DMA_TCD3_ATTR = DMA_TCD_ATTR_SSIZE(0) | DMA_TCD_ATTR_DSIZE(0) | (FREEZE_DEST_ADDR_BITS<<3);;
    DMA_TCD3_NBYTES_MLOFFYES = MLOFFYES;
    DMA_TCD3_SLAST = 0;
    DMA_TCD3_DADDR = &GPIOC_PCOR;
    DMA_TCD3_DOFF = PORT_SPACING;
    DMA_TCD3_CITER_ELINKNO = bufSize/2;
    DMA_TCD3_DLASTSGA = 0;
    DMA_TCD3_CSR = DMA_TCD_CSR_DREQ | DMA_TCD_CSR_INTMAJOR;
    DMA_TCD3_BITER_ELINKNO = bufSize/2;

#endif



#ifdef __MK20DX256__
    MCM_CR = MCM_CR_SRAMLAP(1) | MCM_CR_SRAMUAP(0);
    AXBS_PRS0 = 0x1032;
#endif

    // route the edge detect interrupts to trigger the 3 channels
    DMAMUX0_CHCFG1 = 0;
    DMAMUX0_CHCFG1 = DMAMUX_SOURCE_PORTB | DMAMUX_ENABLE;
    DMAMUX0_CHCFG2 = 0;
    DMAMUX0_CHCFG2 = DMAMUX_SOURCE_PORTC | DMAMUX_ENABLE;
    DMAMUX0_CHCFG3 = 0;
    DMAMUX0_CHCFG3 = DMAMUX_SOURCE_PORTA | DMAMUX_ENABLE;


    // enable a done interrupts when channel #3 completes
    NVIC_ENABLE_IRQ(IRQ_DMA_CH3);
    //pinMode(1, OUTPUT); // testing: oscilloscope trigger
}
Exemplo n.º 18
0
// ------------------------------------------------------------
// this function initializes and starts the timer, using the specified
// function as a callback. must be passed the name of a function taking
// no arguments and returning void. make sure this function can
// complete within the time allowed (aka less than its period)
// ------------------------------------------------------------
void PITimer::start(void (*newISR)()) {
    myISR = newISR;
    isRunning = true;
    *PIT_TCTRL = 3;
    NVIC_ENABLE_IRQ(IRQ_PIT_CH);
}
Exemplo n.º 19
0
Arquivo: ADC.cpp Projeto: jimparis/ADC
/* Enable interrupts: An ADC Interrupt will be raised when the conversion is completed
*  (including hardware averages and if the comparison (if any) is true).
*/
void ADC::enableInterrupts() {
    var_enableInterrupts = 1;
    NVIC_ENABLE_IRQ(IRQ_ADC0);
}