Skip to content

Commit

Permalink
Rework analog pin management
Browse files Browse the repository at this point in the history
Use mask to ease analog pin management and ease alternative
analog pins introduction.
Fix some issues.

Signed-off-by: Frederic Pillon <frederic.pillon@st.com>
  • Loading branch information
fpistm committed Jan 23, 2021
1 parent 51f0492 commit 45cbc5a
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 33 deletions.
37 changes: 28 additions & 9 deletions cores/arduino/pins_arduino.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,28 +67,47 @@ PinName analogInputToPinName(uint32_t pin)
return pn;
}

bool pinIsAnalogInput(uint32_t pin)
/**
* @brief Return true if a digital pin is an analog input
* @param pin Dx, x or PYn
* @retval boolean true if analog or false
*/
bool digitalpinIsAnalogInput(uint32_t pin)
{
bool ret = false;
#if NUM_ANALOG_INPUTS > 0
for (uint32_t i = 0; i < NUM_ANALOG_INPUTS; i++) {
if (analogInputPin[i] == pin) {
ret = true;
break;
if ((pin & PANA) == PANA) {
ret = true;
} else {
for (uint32_t i = 0; i < NUM_ANALOG_INPUTS; i++) {
if (analogInputPin[i] == pin) {
ret = true;
break;
}
}
}
#endif /* NUM_ANALOG_INPUTS > 0 */
return ret;
}

/**
* @brief Return the analog input linked to a digital pin
* @param pin Dx, x or PYn
* @retval analogInput valid analog input or NUM_ANALOG_INPUTS
*/
uint32_t digitalPinToAnalogInput(uint32_t pin)
{
uint32_t ret = NUM_ANALOG_INPUTS;
#if NUM_ANALOG_INPUTS > 0
for (uint32_t i = 0; i < NUM_ANALOG_INPUTS; i++) {
if (analogInputPin[i] == pin) {
ret = i;
break;
if ((pin & PANA) == PANA) {
/* PYn = Ax */
ret = pin & PANA_IDX;
} else {
for (uint32_t i = 0; i < NUM_ANALOG_INPUTS; i++) {
if (analogInputPin[i] == pin) {
ret = i;
break;
}
}
}
#endif /* NUM_ANALOG_INPUTS > 0 */
Expand Down
25 changes: 12 additions & 13 deletions cores/arduino/pins_arduino.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,11 @@ extern const uint32_t analogInputPin[];
/* Convert a digital pin number Dxx to a PinName PX_n */
#if NUM_ANALOG_INPUTS > 0
/* Note: Analog pin is also a digital pin */
#define digitalPinToPinName(p) (((uint32_t)p < NUM_DIGITAL_PINS) ? digitalPin[p] : \
((uint32_t)p >= NUM_ANALOG_FIRST) && ((uint32_t)p <= NUM_ANALOG_LAST) ? \
digitalPin[analogInputPin[p-NUM_ANALOG_FIRST]] : NC)
#define digitalPinToPinName(p) (((uint32_t)(p) < NUM_DIGITAL_PINS) ? digitalPin[p] : \
(((uint32_t)(p) & PANA) == PANA) && ((uint32_t)(p) < NUM_ANALOG_INTERNAL_FIRST) ? \
digitalPin[analogInputPin[(p)&PANA_IDX]] : NC)
#else
#define digitalPinToPinName(p) (((uint32_t)p < NUM_DIGITAL_PINS) ? digitalPin[p] : NC)
#define digitalPinToPinName(p) (((uint32_t)(p) < NUM_DIGITAL_PINS) ? digitalPin[p] : NC)
#endif /* NUM_ANALOG_INPUTS > 0 */
/* Convert a PinName PX_n to a digital pin number */
uint32_t pinNametoDigitalPin(PinName p);
Expand All @@ -98,16 +98,14 @@ uint32_t pinNametoDigitalPin(PinName p);
#if NUM_ANALOG_INPUTS > 0
/* Used by analogRead api to have A0 == 0 */
/* Non contiguous analog pins definition in digitalPin array */
#define analogInputToDigitalPin(p) ( \
((uint32_t)p < NUM_ANALOG_INPUTS) ? analogInputPin[p] : \
((uint32_t)p >= NUM_ANALOG_FIRST) && ((uint32_t)p <= NUM_ANALOG_LAST) ? \
analogInputPin[p-NUM_ANALOG_FIRST] : p)
#else
/* No analog pin defined */
#define analogInputToDigitalPin(p) (((uint32_t)(p) < NUM_ANALOG_INPUTS) ? analogInputPin[p] : \
(((uint32_t)(p) & PANA) == PANA) && ((uint32_t)(p) < NUM_ANALOG_INTERNAL_FIRST) ? \
analogInputPin[(p)&PANA_IDX] : (uint32_t)NC)
#else/* No analog pin defined */
#define analogInputToDigitalPin(p) (NUM_DIGITAL_PINS)
#endif /* NUM_ANALOG_INPUTS > 0 */

/* Convert an analog pin number Axx to a PinName PX_n */
/* Convert an analog pin number Ax to a PinName PX_n */
PinName analogInputToPinName(uint32_t pin);

/* All pins could manage EXTI */
Expand Down Expand Up @@ -166,8 +164,9 @@ PinName analogInputToPinName(uint32_t pin);
#define pinIsSerial(p) ((digitalPinFirstOccurence(p) == PIN_SERIAL_RX) ||\
(digitalPinFirstOccurence(p) == PIN_SERIAL_TX))
#endif
/* Convenient macro to handle Analog */
bool pinIsAnalogInput(uint32_t pin);
/* Convenient macro to handle Analog for Firmata */
#define pinIsAnalogInput digitalpinIsAnalogInput
bool digitalpinIsAnalogInput(uint32_t pin);
uint32_t digitalPinToAnalogInput(uint32_t pin);

#ifdef __cplusplus
Expand Down
18 changes: 11 additions & 7 deletions cores/arduino/pins_arduino_analog.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,34 +15,38 @@
#include "variant.h"
#include "PinNames.h"

/* Analog */
#define PANA 0xC0
/* Analog index */
#define PANA_IDX 0x3F

/* Arduino analog pins */
#ifndef NUM_ANALOG_INPUTS
#define NUM_ANALOG_INPUTS 0
#endif

#define NUM_ANALOG_FIRST (NUM_DIGITAL_PINS + 1)
#define NUM_ANALOG_LAST (NUM_DIGITAL_PINS + NUM_ANALOG_INPUTS)
#define NUM_ANALOG_INTERNAL_FIRST (NUM_ANALOG_LAST + 1)
/* Analog internal pin numbers follow the analog pin number */
#define NUM_ANALOG_INTERNAL_FIRST (PANA + NUM_ANALOG_INPUTS)

/* ADC internal channels (not a pins) */
/* Only used for analogRead() */
#if defined(ADC_CHANNEL_TEMPSENSOR) || defined(ADC_CHANNEL_TEMPSENSOR_ADC1)
#define ATEMP (NUM_ANALOG_INTERNAL_FIRST)
#endif
#ifdef ADC_CHANNEL_VREFINT
#define AVREF (NUM_ANALOG_INTERNAL_FIRST + 2)
#define AVREF (NUM_ANALOG_INTERNAL_FIRST + 1)
#endif
#ifdef ADC_CHANNEL_VBAT
#define AVBAT (NUM_ANALOG_INTERNAL_FIRST + 3)
#define AVBAT (NUM_ANALOG_INTERNAL_FIRST + 2)
#endif
#if defined(ADC5) && defined(ADC_CHANNEL_TEMPSENSOR_ADC5)
#define ATEMP_ADC5 (NUM_ANALOG_INTERNAL_FIRST + 4)
#define ATEMP_ADC5 (NUM_ANALOG_INTERNAL_FIRST + 3)
#endif

/* If NUM_ANALOG_INPUTS is not defined there is no analog pins defined. */
/* Anyway ADC internal channels are always available. */
#if NUM_ANALOG_INPUTS > 0
#define PIN_A0 NUM_ANALOG_FIRST
#define PIN_A0 PANA
static const uint8_t A0 = PIN_A0;
#if NUM_ANALOG_INPUTS > 1
#define PIN_A1 (PIN_A0 + 1)
Expand Down
8 changes: 5 additions & 3 deletions cores/arduino/stm32/PinNames.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ extern "C" {
#define ALT5 0x600
#define ALT6 0x700

// Specific pins
// Specific pinmap definition
// Analog internal
#define PANAINT 0x1000
// Dual pad pin
// Direct channels are connected to analog I/Os
// (PY_C) to optimize ADC performance.
Expand All @@ -29,7 +31,7 @@ extern "C" {

typedef enum {
// Not connected
NC = (int)0xFFFFFFFF,
NC = 0xFFFFFFFF,

// Pin name definition
PA_0 = (PortA << 4) + 0x00,
Expand Down Expand Up @@ -246,7 +248,7 @@ typedef enum {
PZ_15 = (PortZ << 4) + 0x0F,
#endif
// Specific pin name
PADC_BASE = 0x100,
PADC_BASE = PANAINT,
#if defined(ADC_CHANNEL_TEMPSENSOR) || defined(ADC_CHANNEL_TEMPSENSOR_ADC1)
PADC_TEMP,
#endif
Expand Down
4 changes: 3 additions & 1 deletion keywords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,6 @@ PIN_A23 LITERAL1

NUM_DIGITAL_PINS LITERAL1
NUM_ANALOG_INPUTS LITERAL1
NUM_ANALOG_FIRST LITERAL1
MAX_ANALOG_INPUTS LITERAL1
NOT_AN_INTERRUPT LITERAL1

Expand Down Expand Up @@ -344,6 +343,7 @@ LED_RED LITERAL1

digitalPinToPinName KEYWORD2
analogInputToDigitalPin KEYWORD2
analogInputToPinName KEYWORD2
digitalPinHasI2C KEYWORD2
digitalPinHasPWM KEYWORD2
digitalPinHasSerial KEYWORD2
Expand Down Expand Up @@ -733,6 +733,8 @@ ALT3 LITERAL1
ALT4 LITERAL1
ALT5 LITERAL1
ALT6 LITERAL1
PANA LITERAL1
PANAINT LITERAL1
PDUAL LITERAL1
PREMAP LITERAL1

Expand Down

0 comments on commit 45cbc5a

Please sign in to comment.