aboutsummaryrefslogtreecommitdiffstats
path: root/os/hal/ports/AVR/adc_lld.c
diff options
context:
space:
mode:
authorutzig <utzig@35acf78f-673a-0410-8e92-d51de3d6d3f4>2014-06-29 23:06:17 +0000
committerutzig <utzig@35acf78f-673a-0410-8e92-d51de3d6d3f4>2014-06-29 23:06:17 +0000
commit766a2388d46f49e07ec0280fa4f3d254367850d1 (patch)
treef7c116f3a638a861575a16467703ad19fd26255c /os/hal/ports/AVR/adc_lld.c
parent5eb1ae8cc3f4d2584d31e2d9672162bf8bfc0274 (diff)
downloadChibiOS-766a2388d46f49e07ec0280fa4f3d254367850d1.tar.gz
ChibiOS-766a2388d46f49e07ec0280fa4f3d254367850d1.tar.bz2
ChibiOS-766a2388d46f49e07ec0280fa4f3d254367850d1.zip
AVR HAL ported from RT-2 (serial/pal/hal tested)
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@6999 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os/hal/ports/AVR/adc_lld.c')
-rw-r--r--os/hal/ports/AVR/adc_lld.c190
1 files changed, 190 insertions, 0 deletions
diff --git a/os/hal/ports/AVR/adc_lld.c b/os/hal/ports/AVR/adc_lld.c
new file mode 100644
index 000000000..e41a2122e
--- /dev/null
+++ b/os/hal/ports/AVR/adc_lld.c
@@ -0,0 +1,190 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2014 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file AVR/adc_lld.c
+ * @brief ADC Driver subsystem low level driver source.
+ *
+ * @addtogroup ADC
+ * @{
+ */
+
+#include "hal.h"
+
+#if HAL_USE_ADC || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+/** @brief ADC1 driver identifier.*/
+#if AVR_ADC_USE_ADC1 || defined(__DOXYGEN__)
+ADCDriver ADCD1;
+#endif
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static size_t getAdcChannelNumberFromMask(uint8_t mask, uint8_t currentChannel) {
+
+ for (uint8_t i = 0; mask > 0; i++) {
+ if (mask & 0x01) {
+ if (!currentChannel)
+ return i;
+ currentChannel--;
+ }
+ mask >>= 1;
+ }
+
+ /* error, should never reach this line */
+}
+
+static void setAdcChannel(uint8_t channelNum) {
+
+ ADMUX = (ADMUX & 0xf8) | (channelNum & 0x07);
+
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#include <util/delay.h>
+
+OSAL_IRQ_HANDLER(ADC_vect) {
+
+ OSAL_IRQ_PROLOGUE();
+ uint8_t low = ADCL;
+ uint8_t high = ADCH;
+ uint16_t result = (high << 8) | low;
+
+ ADCD1.samples[ADCD1.currentBufferPosition] = result;
+ ADCD1.currentBufferPosition++;
+
+ size_t bufferSize = ADCD1.depth * ADCD1.grpp->num_channels;
+ size_t currentChannel = ADCD1.currentBufferPosition % ADCD1.grpp->num_channels;
+ size_t currentIteration = ADCD1.currentBufferPosition / ADCD1.grpp->num_channels;
+ if (ADCD1.grpp->circular && currentChannel == 0 && currentIteration == ADCD1.depth/2) {
+ _adc_isr_half_code(&ADCD1);
+ }
+
+ if (ADCD1.currentBufferPosition == bufferSize) {
+ _adc_isr_full_code(&ADCD1);
+ } else {
+ setAdcChannel(getAdcChannelNumberFromMask(ADCD1.grpp->channelsMask,currentChannel));
+ ADCSRA |= 1 << ADSC;
+ }
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level ADC driver initialization.
+ *
+ * @notapi
+ */
+void adc_lld_init(void) {
+
+ adcObjectInit(&ADCD1);
+
+ //prescaler 128, only value possible at 20Mhz, interrupt
+ ADCSRA = (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0) | (1 << ADIE);
+
+ ADCSRB = 0; //single shot
+
+ //uso aref, only valid for arduino. arduino ha aref collegato
+ ADMUX = (0 << REFS1) | (0 << REFS0);
+
+}
+
+/**
+ * @brief Configures and activates the ADC peripheral.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adc_lld_start(ADCDriver *adcp) {
+
+ if (adcp->state == ADC_STOP) {
+ /* Clock activation.*/
+ ADCSRA |= (1 << ADEN);
+ }
+
+ if (adcp->config != NULL) {
+ ADMUX = (adcp->config->analog_reference << REFS0);
+ }
+}
+
+/**
+ * @brief Deactivates the ADC peripheral.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adc_lld_stop(ADCDriver *adcp) {
+
+ if (adcp->state == ADC_READY) {
+ /* Clock de-activation.*/
+ ADCSRA &= ~(1 << ADEN);
+ }
+
+}
+
+/**
+ * @brief Starts an ADC conversion.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adc_lld_start_conversion(ADCDriver *adcp) {
+
+ adcp->currentBufferPosition=0;
+
+ setAdcChannel(getAdcChannelNumberFromMask(adcp->grpp->channelsMask,0));
+ ADCSRA |= 1 << ADSC;
+
+}
+
+/**
+ * @brief Stops an ongoing conversion.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adc_lld_stop_conversion(ADCDriver *adcp) {
+
+ ADCSRA &= ~(1 << ADSC);
+
+}
+
+#endif /* HAL_USE_ADC */
+
+/** @} */