mbed library sources. Supersedes mbed-src.
Dependents: Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more
targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/analogin_api.c@189:f392fc9709a3, 2019-02-20 (annotated)
- Committer:
- AnnaBridge
- Date:
- Wed Feb 20 22:31:08 2019 +0000
- Revision:
- 189:f392fc9709a3
- Parent:
- 168:9672193075cf
mbed library release version 165
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
AnnaBridge | 168:9672193075cf | 1 | /* mbed Microcontroller Library |
AnnaBridge | 168:9672193075cf | 2 | * Copyright (c) 2017 ARM Limited |
AnnaBridge | 168:9672193075cf | 3 | * |
AnnaBridge | 168:9672193075cf | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
AnnaBridge | 168:9672193075cf | 5 | * you may not use this file except in compliance with the License. |
AnnaBridge | 168:9672193075cf | 6 | * You may obtain a copy of the License at |
AnnaBridge | 168:9672193075cf | 7 | * |
AnnaBridge | 168:9672193075cf | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
AnnaBridge | 168:9672193075cf | 9 | * |
AnnaBridge | 168:9672193075cf | 10 | * Unless required by applicable law or agreed to in writing, software |
AnnaBridge | 168:9672193075cf | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
AnnaBridge | 168:9672193075cf | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
AnnaBridge | 168:9672193075cf | 13 | * See the License for the specific language governing permissions and |
AnnaBridge | 168:9672193075cf | 14 | * limitations under the License. |
AnnaBridge | 168:9672193075cf | 15 | */ |
AnnaBridge | 168:9672193075cf | 16 | |
AnnaBridge | 168:9672193075cf | 17 | /* |
AnnaBridge | 168:9672193075cf | 18 | * This HAL implementation uses the AD7490 analog-to-digital converter |
AnnaBridge | 168:9672193075cf | 19 | * available on the MPS2 Adapter for Arduino shields. |
AnnaBridge | 168:9672193075cf | 20 | */ |
AnnaBridge | 168:9672193075cf | 21 | |
AnnaBridge | 168:9672193075cf | 22 | #include "analogin_api.h" |
AnnaBridge | 168:9672193075cf | 23 | #include "gpio_api.h" |
AnnaBridge | 168:9672193075cf | 24 | #include "spi_api.h" |
AnnaBridge | 168:9672193075cf | 25 | #include "mbed_error.h" |
AnnaBridge | 168:9672193075cf | 26 | #include "mbed_wait_api.h" |
AnnaBridge | 168:9672193075cf | 27 | #include "pinmap.h" |
AnnaBridge | 168:9672193075cf | 28 | |
AnnaBridge | 168:9672193075cf | 29 | /* |
AnnaBridge | 168:9672193075cf | 30 | * There is only one AD7490 controller to read the analog pins in both shields. |
AnnaBridge | 168:9672193075cf | 31 | * The AD7490 documentation (AD7490.pdf, page 12) tells us the right control |
AnnaBridge | 168:9672193075cf | 32 | * register to send. |
AnnaBridge | 168:9672193075cf | 33 | */ |
AnnaBridge | 168:9672193075cf | 34 | |
AnnaBridge | 168:9672193075cf | 35 | /* Output conversion is straight binary */ |
AnnaBridge | 168:9672193075cf | 36 | #define CODING (1 << 0) |
AnnaBridge | 168:9672193075cf | 37 | /* Analog input range from 0 to REF_IN volts */ |
AnnaBridge | 168:9672193075cf | 38 | #define RANGE (1 << 1) |
AnnaBridge | 168:9672193075cf | 39 | /* DOUT line state, weakly driven or three-state */ |
AnnaBridge | 168:9672193075cf | 40 | #define WEAK_TRI (1 << 2) |
AnnaBridge | 168:9672193075cf | 41 | /* Access to the shadow register */ |
AnnaBridge | 168:9672193075cf | 42 | #define SHADOW (1 << 3) |
AnnaBridge | 168:9672193075cf | 43 | /* Normal operation power mode */ |
AnnaBridge | 168:9672193075cf | 44 | #define PM0 (1 << 4) |
AnnaBridge | 168:9672193075cf | 45 | /* Normal operation power mode */ |
AnnaBridge | 168:9672193075cf | 46 | #define PM1 (1 << 5) |
AnnaBridge | 168:9672193075cf | 47 | /* Write control register */ |
AnnaBridge | 168:9672193075cf | 48 | #define WRITE (1 << 11) |
AnnaBridge | 168:9672193075cf | 49 | #define NORMAL_CONTROL_REGISTER (CODING | RANGE | PM0 | PM1 | WRITE) |
AnnaBridge | 168:9672193075cf | 50 | /* The ADC will ignore the write of this control register */ |
AnnaBridge | 168:9672193075cf | 51 | #define NO_WRITE_CONTROL_REGISTER 0x000 |
AnnaBridge | 168:9672193075cf | 52 | /* Bit position of the channel number in the control register */ |
AnnaBridge | 168:9672193075cf | 53 | #define CHANNEL_NUMBER_POSITION 6 |
AnnaBridge | 168:9672193075cf | 54 | /* CS signal of the ADC needs to be put low during transfers */ |
AnnaBridge | 168:9672193075cf | 55 | #define CS_LOW 0 |
AnnaBridge | 168:9672193075cf | 56 | #define CS_HIGH 1 |
AnnaBridge | 168:9672193075cf | 57 | /* The ADC expects a 16 bits word but only read the 12 most significant bits */ |
AnnaBridge | 168:9672193075cf | 58 | #define USELESS_ADC_BITS 4 |
AnnaBridge | 168:9672193075cf | 59 | /* The ADC result is on the 12 least significant bits */ |
AnnaBridge | 168:9672193075cf | 60 | #define OUTPUT_DATA_MASK 0xFFF |
AnnaBridge | 168:9672193075cf | 61 | /* The maximum value is the biggest value than can be coded on 12 bits */ |
AnnaBridge | 168:9672193075cf | 62 | #define MAXIMUM_VALUE_12_BITS OUTPUT_DATA_MASK |
AnnaBridge | 168:9672193075cf | 63 | #define FRAME_16_BITS 16 |
AnnaBridge | 168:9672193075cf | 64 | #define NO_POLARITY_NO_PHASE 0 |
AnnaBridge | 168:9672193075cf | 65 | #define MASTER_MODE 0 |
AnnaBridge | 168:9672193075cf | 66 | /* Maximal SPI frequency as written in the ADC documentation */ |
AnnaBridge | 168:9672193075cf | 67 | #define MAXIMAL_SPI_FREQUENCY_HZ 12000000 |
AnnaBridge | 168:9672193075cf | 68 | |
AnnaBridge | 168:9672193075cf | 69 | /* The value of the peripheral constant linked with one analog pins is the |
AnnaBridge | 168:9672193075cf | 70 | * channel number of that pin on the ADC: |
AnnaBridge | 168:9672193075cf | 71 | * A0_0 is channel 0 |
AnnaBridge | 168:9672193075cf | 72 | * ... |
AnnaBridge | 168:9672193075cf | 73 | * A0_5 is channel 5 |
AnnaBridge | 168:9672193075cf | 74 | * A1_0 is channel 6 |
AnnaBridge | 168:9672193075cf | 75 | * ... |
AnnaBridge | 168:9672193075cf | 76 | * A1_5 is channel 11 |
AnnaBridge | 168:9672193075cf | 77 | */ |
AnnaBridge | 168:9672193075cf | 78 | static const PinMap PinMap_ADC[] = { |
AnnaBridge | 168:9672193075cf | 79 | {A0_0, ADC0_0, 0}, |
AnnaBridge | 168:9672193075cf | 80 | {A0_1, ADC0_1, 0}, |
AnnaBridge | 168:9672193075cf | 81 | {A0_2, ADC0_2, 0}, |
AnnaBridge | 168:9672193075cf | 82 | {A0_3, ADC0_3, 0}, |
AnnaBridge | 168:9672193075cf | 83 | {A0_4, ADC0_4, 0}, |
AnnaBridge | 168:9672193075cf | 84 | {A0_5, ADC0_5, 0}, |
AnnaBridge | 168:9672193075cf | 85 | {A1_0, ADC0_6, 0}, |
AnnaBridge | 168:9672193075cf | 86 | {A1_1, ADC0_7, 0}, |
AnnaBridge | 168:9672193075cf | 87 | {A1_2, ADC0_8, 0}, |
AnnaBridge | 168:9672193075cf | 88 | {A1_3, ADC0_9, 0}, |
AnnaBridge | 168:9672193075cf | 89 | {A1_4, ADC0_10, 0}, |
AnnaBridge | 168:9672193075cf | 90 | {A1_5, ADC0_11, 0}, |
AnnaBridge | 168:9672193075cf | 91 | {NC , NC, 0} |
AnnaBridge | 168:9672193075cf | 92 | }; |
AnnaBridge | 168:9672193075cf | 93 | |
AnnaBridge | 168:9672193075cf | 94 | /* mbed OS gpio_t structure for the CS pin linked to the ADC */ |
AnnaBridge | 168:9672193075cf | 95 | static gpio_t adc_cs; |
AnnaBridge | 168:9672193075cf | 96 | |
AnnaBridge | 168:9672193075cf | 97 | /* mbed OS spi_t structure to communicate with the ADC */ |
AnnaBridge | 168:9672193075cf | 98 | static spi_t adc_spi; |
AnnaBridge | 168:9672193075cf | 99 | |
AnnaBridge | 168:9672193075cf | 100 | void analogin_init(analogin_t *obj, PinName pin) |
AnnaBridge | 168:9672193075cf | 101 | { |
AnnaBridge | 168:9672193075cf | 102 | uint16_t control_register = NORMAL_CONTROL_REGISTER; |
AnnaBridge | 168:9672193075cf | 103 | uint32_t channel_number = pinmap_peripheral(pin, PinMap_ADC); |
AnnaBridge | 168:9672193075cf | 104 | |
AnnaBridge | 168:9672193075cf | 105 | if (channel_number == (uint32_t)NC) { |
AnnaBridge | 168:9672193075cf | 106 | error("pin %d is not connected to the ADC", pin); |
AnnaBridge | 168:9672193075cf | 107 | } |
AnnaBridge | 168:9672193075cf | 108 | |
AnnaBridge | 168:9672193075cf | 109 | /* Add the channel number to the control register */ |
AnnaBridge | 168:9672193075cf | 110 | control_register |= (channel_number << CHANNEL_NUMBER_POSITION); |
AnnaBridge | 168:9672193075cf | 111 | /* Only the 12 first bits are taken into account */ |
AnnaBridge | 168:9672193075cf | 112 | control_register <<= USELESS_ADC_BITS; |
AnnaBridge | 168:9672193075cf | 113 | obj->ctrl_register = control_register; |
AnnaBridge | 168:9672193075cf | 114 | |
AnnaBridge | 168:9672193075cf | 115 | spi_init(&adc_spi, ADC_MOSI, ADC_MISO, ADC_SCLK, NC); |
AnnaBridge | 168:9672193075cf | 116 | spi_format(&adc_spi, FRAME_16_BITS, NO_POLARITY_NO_PHASE, MASTER_MODE); |
AnnaBridge | 168:9672193075cf | 117 | spi_frequency(&adc_spi, MAXIMAL_SPI_FREQUENCY_HZ); |
AnnaBridge | 168:9672193075cf | 118 | |
AnnaBridge | 168:9672193075cf | 119 | gpio_init_out(&adc_cs, ADC_SSEL); |
AnnaBridge | 168:9672193075cf | 120 | } |
AnnaBridge | 168:9672193075cf | 121 | |
AnnaBridge | 168:9672193075cf | 122 | uint16_t analogin_read_u16(analogin_t *obj) |
AnnaBridge | 168:9672193075cf | 123 | { |
AnnaBridge | 168:9672193075cf | 124 | uint16_t result; |
AnnaBridge | 168:9672193075cf | 125 | |
AnnaBridge | 168:9672193075cf | 126 | /* Request conversion */ |
AnnaBridge | 168:9672193075cf | 127 | gpio_write(&adc_cs, CS_LOW); |
AnnaBridge | 168:9672193075cf | 128 | /* Only write the control register, ignore the previous results */ |
AnnaBridge | 168:9672193075cf | 129 | (void)spi_master_write(&adc_spi, obj->ctrl_register); |
AnnaBridge | 168:9672193075cf | 130 | gpio_write(&adc_cs, CS_HIGH); |
AnnaBridge | 168:9672193075cf | 131 | |
AnnaBridge | 168:9672193075cf | 132 | /* |
AnnaBridge | 168:9672193075cf | 133 | * According to the documentation, t_QUIET (50 ns) time needs to pass before |
AnnaBridge | 168:9672193075cf | 134 | * accessing to the SPI bus again. We wait here 1 us as we can not wait a |
AnnaBridge | 168:9672193075cf | 135 | * shorter time than that. |
AnnaBridge | 168:9672193075cf | 136 | */ |
AnnaBridge | 168:9672193075cf | 137 | wait_us(1); |
AnnaBridge | 168:9672193075cf | 138 | |
AnnaBridge | 168:9672193075cf | 139 | /* Read conversion result */ |
AnnaBridge | 168:9672193075cf | 140 | gpio_write(&adc_cs, CS_LOW); |
AnnaBridge | 168:9672193075cf | 141 | /* Only read the results without writing the control register */ |
AnnaBridge | 168:9672193075cf | 142 | result = spi_master_write(&adc_spi, NO_WRITE_CONTROL_REGISTER); |
AnnaBridge | 168:9672193075cf | 143 | gpio_write(&adc_cs, CS_HIGH); |
AnnaBridge | 168:9672193075cf | 144 | |
AnnaBridge | 168:9672193075cf | 145 | return (result & OUTPUT_DATA_MASK); |
AnnaBridge | 168:9672193075cf | 146 | } |
AnnaBridge | 168:9672193075cf | 147 | |
AnnaBridge | 168:9672193075cf | 148 | float analogin_read(analogin_t *obj) |
AnnaBridge | 168:9672193075cf | 149 | { |
AnnaBridge | 168:9672193075cf | 150 | uint16_t result = analogin_read_u16(obj); |
AnnaBridge | 168:9672193075cf | 151 | |
AnnaBridge | 168:9672193075cf | 152 | return (result * (1. / MAXIMUM_VALUE_12_BITS)); |
AnnaBridge | 168:9672193075cf | 153 | } |