/* mbed Microcontroller Library * Copyright (c) 2017 ARM Limited * SPDX-License-Identifier: Apache-2.0 * * 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. */ /* * This HAL implementation uses the AD7490 analog-to-digital converter * available on the MPS2 Adapter for Arduino shields. */ #include "analogin_api.h" #include "gpio_api.h" #include "spi_api.h" #include "mbed_error.h" #include "mbed_wait_api.h" #include "pinmap.h" /* * There is only one AD7490 controller to read the analog pins in both shields. * The AD7490 documentation (AD7490.pdf, page 12) tells us the right control * register to send. */ /* Output conversion is straight binary */ #define CODING (1 << 0) /* Analog input range from 0 to REF_IN volts */ #define RANGE (1 << 1) /* DOUT line state, weakly driven or three-state */ #define WEAK_TRI (1 << 2) /* Access to the shadow register */ #define SHADOW (1 << 3) /* Normal operation power mode */ #define PM0 (1 << 4) /* Normal operation power mode */ #define PM1 (1 << 5) /* Write control register */ #define WRITE (1 << 11) #define NORMAL_CONTROL_REGISTER (CODING | RANGE | PM0 | PM1 | WRITE) /* The ADC will ignore the write of this control register */ #define NO_WRITE_CONTROL_REGISTER 0x000 /* Bit position of the channel number in the control register */ #define CHANNEL_NUMBER_POSITION 6 /* CS signal of the ADC needs to be put low during transfers */ #define CS_LOW 0 #define CS_HIGH 1 /* The ADC expects a 16 bits word but only read the 12 most significant bits */ #define USELESS_ADC_BITS 4 /* The ADC result is on the 12 least significant bits */ #define OUTPUT_DATA_MASK 0xFFF /* The maximum value is the biggest value than can be coded on 12 bits */ #define MAXIMUM_VALUE_12_BITS OUTPUT_DATA_MASK #define FRAME_16_BITS 16 #define NO_POLARITY_NO_PHASE 0 #define MASTER_MODE 0 /* Maximal SPI frequency as written in the ADC documentation */ #define MAXIMAL_SPI_FREQUENCY_HZ 12000000 /* The value of the peripheral constant linked with one analog pins is the * channel number of that pin on the ADC: * A0_0 is channel 0 * ... * A0_5 is channel 5 * A1_0 is channel 6 * ... * A1_5 is channel 11 */ static const PinMap PinMap_ADC[] = { {A0_0, ADC0_0, 0}, {A0_1, ADC0_1, 0}, {A0_2, ADC0_2, 0}, {A0_3, ADC0_3, 0}, {A0_4, ADC0_4, 0}, {A0_5, ADC0_5, 0}, {A1_0, ADC0_6, 0}, {A1_1, ADC0_7, 0}, {A1_2, ADC0_8, 0}, {A1_3, ADC0_9, 0}, {A1_4, ADC0_10, 0}, {A1_5, ADC0_11, 0}, {NC , NC, 0} }; /* mbed OS gpio_t structure for the CS pin linked to the ADC */ static gpio_t adc_cs; /* mbed OS spi_t structure to communicate with the ADC */ static spi_t adc_spi; void analogin_init(analogin_t *obj, PinName pin) { uint16_t control_register = NORMAL_CONTROL_REGISTER; uint32_t channel_number = pinmap_peripheral(pin, PinMap_ADC); if (channel_number == (uint32_t)NC) { error("pin %d is not connected to the ADC", pin); } /* Add the channel number to the control register */ control_register |= (channel_number << CHANNEL_NUMBER_POSITION); /* Only the 12 first bits are taken into account */ control_register <<= USELESS_ADC_BITS; obj->ctrl_register = control_register; spi_init(&adc_spi, ADC_MOSI, ADC_MISO, ADC_SCLK, NC); spi_format(&adc_spi, FRAME_16_BITS, NO_POLARITY_NO_PHASE, MASTER_MODE); spi_frequency(&adc_spi, MAXIMAL_SPI_FREQUENCY_HZ); gpio_init_out(&adc_cs, ADC_SSEL); } uint16_t analogin_read_u16(analogin_t *obj) { uint16_t result; /* Request conversion */ gpio_write(&adc_cs, CS_LOW); /* Only write the control register, ignore the previous results */ (void)spi_master_write(&adc_spi, obj->ctrl_register); gpio_write(&adc_cs, CS_HIGH); /* * According to the documentation, t_QUIET (50 ns) time needs to pass before * accessing to the SPI bus again. We wait here 1 us as we can not wait a * shorter time than that. */ wait_us(1); /* Read conversion result */ gpio_write(&adc_cs, CS_LOW); /* Only read the results without writing the control register */ result = spi_master_write(&adc_spi, NO_WRITE_CONTROL_REGISTER); gpio_write(&adc_cs, CS_HIGH); return (result & OUTPUT_DATA_MASK); } float analogin_read(analogin_t *obj) { uint16_t result = analogin_read_u16(obj); return (result * (1. / MAXIMUM_VALUE_12_BITS)); } const PinMap *analogin_pinmap() { return PinMap_ADC; }