bool adc_enable(adc* adc0) { // Find position in ADC list adc** a = &adcs; while (*a != NULL && adc_get_channel(*a) <= adc_get_channel(adc0)) { if (*a == adc0) { return false; } a = &((*a)->next); } // Initialize ADC adc0->next_value = 0; reset_samples_remaining(adc0); // Add new ADC to list adc0->next = *a; *a = adc0; // Disable digital input on channel to save power ADC_DIGITAL_INPUT_DISABLE(adc_get_channel(adc0)); // Notify the ADC process that the ADC list has changed process_post_event(&adc_process, EVENT_ADC_LIST_CHANGED, PROCESS_DATA_NULL); return true; }
/** * \brief Read configuration from ADC channel * * Reads out the current configuration from the ADC channel to the specified * buffer. * * \param adc Pointer to ADC module. * \param ch_mask Mask of ADC channel(s): * \arg \c ADC_CHn , where \c n specifies the channel. (Only a single channel * can be given in mask) * \param ch_conf Pointer to ADC channel configuration. */ void adcch_read_configuration(ADC_t *adc, uint8_t ch_mask, struct adc_channel_config *ch_conf) { ADC_CH_t *adc_ch; irqflags_t flags; adc_ch = adc_get_channel(adc, ch_mask); flags = cpu_irq_save(); adc_enable_clock(adc); ch_conf->ctrl = adc_ch->CTRL; ch_conf->intctrl = adc_ch->INTCTRL; ch_conf->muxctrl = adc_ch->MUXCTRL; ch_conf->scan = adc_ch->SCAN; ch_conf->corrctrl = adc_ch->CORRCTRL; ch_conf->offsetcorr0 = adc_ch->OFFSETCORR0; ch_conf->offsetcorr1 = adc_ch->OFFSETCORR1; ch_conf->gaincorr0 = adc_ch->GAINCORR0; ch_conf->gaincorr1 = adc_ch->GAINCORR1; ch_conf->avgctrl = adc_ch->AVGCTRL; adc_disable_clock(adc); cpu_irq_restore(flags); }
bool adc_disable(adc* adc0) { bool only_adc_for_channel = true; // Find position in list adc** a = &adcs; while (*a != NULL && *a != adc0) { if (adc_get_channel(*a) == adc_get_channel(adc0)) { only_adc_for_channel = false; } a = &((*a)->next); } if (*a == NULL) { return false; } // Make sure we do not consider this ADC for the next channel to queue. if (next_adc_to_consider == adc0) { next_adc_to_consider = adc0->next; } ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { // Prevent the ISR from messing with this ADC structure adc0->samples_remaining = 0; } // Remove ADC from list *a = (*a)->next; adc0->next = NULL; // Check channel of next ADC in list only_adc_for_channel = only_adc_for_channel && ((*a) == NULL || adc_get_channel(*a) != adc_get_channel(adc0)); // Re-enable the digital input if there are no other ADC's for the same // channel in the list if (only_adc_for_channel) { ADC_DIGITAL_INPUT_ENABLE(adc_get_channel(adc0)); } return true; }
void display_adc_readings(void) { unsigned long adc_reading=0; adc_reading=adc_get_channel(0); adc_reading=(adc_reading*10000)/adc_1Vx10; lcd_gotoxy(4,0); lcd_puti(adc_reading,3); adc_reading=adc_get_channel(4); adc_reading=(adc_reading*10000)/adc_1Vx10; lcd_gotoxy(15,0); lcd_puti(adc_reading,3); adc_reading=adc_get_channel(1); adc_reading=(adc_reading*10000)/adc_1Vx10; lcd_gotoxy(4,1); lcd_puti(adc_reading,3); adc_reading=adc_get_channel(5); adc_reading=(adc_reading*10000)/adc_1Vx10; lcd_gotoxy(15,1); lcd_puti(adc_reading,3); adc_reading=adc_get_channel(2); adc_reading=(adc_reading*10000)/adc_1Vx10; lcd_gotoxy(4,2); lcd_puti(adc_reading,3); adc_reading=adc_get_channel(6); adc_reading=(adc_reading*10000)/adc_1Vx10; lcd_gotoxy(15,2); lcd_puti(adc_reading,3); adc_reading=adc_get_channel(3); adc_reading=(adc_reading*10000)/adc_1Vx10; lcd_gotoxy(4,3); lcd_puti(adc_reading,3); adc_reading=adc_get_channel(7); adc_reading=(adc_reading*10000)/adc_1Vx10; lcd_gotoxy(15,3); lcd_puti(adc_reading,3); return; }
/** * \brief Write configuration to ADC channel * * Writes the specified configuration to the ADC channel. * * \param adc Pointer to ADC module. * \param ch_mask Mask of ADC channel(s): * \arg \c ADC_CHn , where \c n specifies the channel. (Only a single channel * can be given in mask) * \param ch_conf Pointer to ADC channel configuration. * * \note The specified ADC's callback function must be set before this function * is called if callbacks are enabled and interrupts are enabled in the * channel configuration. */ void adcch_write_configuration(ADC_t *adc, uint8_t ch_mask, const struct adc_channel_config *ch_conf) { ADC_CH_tmpfix_t *adc_ch; irqflags_t flags; adc_ch = adc_get_channel(adc, ch_mask); flags = cpu_irq_save(); #if defined(CONFIG_ADC_CALLBACK_ENABLE) && defined(_ASSERT_ENABLE_) if ((adc_ch->INTCTRL & ADC_CH_INTLVL_gm) != ADC_CH_INTLVL_OFF_gc) { # ifdef ADCA if ((uintptr_t)adc == (uintptr_t)&ADCA) { Assert(adca_callback); } else # endif # ifdef ADCB if ((uintptr_t)adc == (uintptr_t)&ADCB) { Assert(adcb_callback); } else # endif { Assert(0); return; } } #endif adc_enable_clock(adc); adc_ch->CTRL = ch_conf->ctrl; adc_ch->INTCTRL = ch_conf->intctrl; adc_ch->MUXCTRL = ch_conf->muxctrl; #if CONFIG_ADC_VERSION == 2 if (ch_mask & ADC_CH0) { /* USB devices has channel scan available on ADC channel 0 */ adc_ch->SCAN = ch_conf->scan; } #endif adc_disable_clock(adc); cpu_irq_restore(flags); }
/** * \brief Write configuration to ADC channel * * Writes the specified configuration to the ADC channel. * * \param adc Pointer to ADC module. * \param ch_mask Mask of ADC channel(s): * \arg \c ADC_CHn , where \c n specifies the channel. (Only a single channel * can be given in mask) * \param ch_conf Pointer to ADC channel configuration. * * \note The specified ADC's callback function must be set before this function * is called if callbacks are enabled and interrupts are enabled in the * channel configuration. */ void adcch_write_configuration(ADC_t *adc, uint8_t ch_mask, const struct adc_channel_config *ch_conf) { ADC_CH_t *adc_ch; irqflags_t flags; adc_ch = adc_get_channel(adc, ch_mask); flags = cpu_irq_save(); #if defined(CONFIG_ADC_CALLBACK_ENABLE) && defined(_ASSERT_ENABLE_) if ((adc_ch->INTCTRL & ADC_CH_INTLVL_gm) != ADC_CH_INTLVL_OFF_gc) { # ifdef ADCA if ((uintptr_t)adc == (uintptr_t)&ADCA) { Assert(adca_callback); } else # endif { Assert(0); return; } } #endif adc_enable_clock(adc); adc_ch->CTRL = ch_conf->ctrl; adc_ch->INTCTRL = ch_conf->intctrl; adc_ch->MUXCTRL = ch_conf->muxctrl; adc_ch->SCAN = ch_conf->scan; adc_ch->CORRCTRL = ch_conf->corrctrl; adc_ch->OFFSETCORR0 = ch_conf->offsetcorr0; adc_ch->OFFSETCORR1 = ch_conf->offsetcorr1; adc_ch->GAINCORR0 = ch_conf->gaincorr0; adc_ch->GAINCORR1 = ch_conf->gaincorr1; adc_ch->AVGCTRL = ch_conf->avgctrl; adc_disable_clock(adc); cpu_irq_restore(flags); }
/** * \brief Read configuration from ADC channel * * Reads out the current configuration from the ADC channel to the specified * buffer. * * \param adc Pointer to ADC module. * \param ch_mask Mask of ADC channel(s): * \arg \c ADC_CHn , where \c n specifies the channel. (Only a single channel * can be given in mask) * \param ch_conf Pointer to ADC channel configuration. */ void adcch_read_configuration(ADC_t * adc, uint8_t ch_mask, struct adc_channel_config *ch_conf) { ADC_CH_t *adc_ch; irqflags_t flags; adc_ch = adc_get_channel(adc, ch_mask); flags = cpu_irq_save(); adc_enable_clock(adc); ch_conf->ctrl = adc_ch->CTRL; ch_conf->intctrl = adc_ch->INTCTRL; ch_conf->muxctrl = adc_ch->MUXCTRL; if (ch_mask & ADC_CH0) { /* USB devices has channel scan available on ADC channel 0 */ ch_conf->scan = adc_ch->SCAN; } adc_disable_clock(adc); cpu_irq_restore(flags); }