1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/sys/arduino/base.cpp
Marian Buschsieweke 043e8cc88e
boards,sys/arduino: major clean up
- Rename all `arduino_pinmap.h` to `arduino_iomap.h`
    - An empty `arduino_pinmap.h` that just includes `arduino_iomap.h`
      is provided for backward compatibility
    - Move all info from `arduino_board.h` into the new file as trivial
      macros, so that they can also be used outside of sketches
    - The new name reflects the fact not just pin mappings, but also
      other I/O features such as PWMs are mapped
- Drop all `arduino_board.h`
    - `arduino_board.h` and `arduino_iomap.h` now provide the exact
      same information, just in a different format
    - a generic `arduino_board.h` is provided instead that just
      uses the info in `arduinio_iomap.h` and provides them in the
      format the code in `sys/arduino` expects it
- Add fine grained features to indicate for mappings
    - availability of mappings for analog pins, DAC pins, PWM pins,
      UART devices, SPI/I2C buses to the corresponding RIOT
      identification can now be expressed:
        - `arduino_pins`: `ARDUINO_PIN_0` etc. are available
        - `arduino_analog`: `ARDUINO_A0` etc. are available
        - `arduino_pwm`: `ARDUINO_PIN_13_PWM_DEV` etc. are available
        - `arduino_dac`: `ARDUINO_DAC0` etc. are available
        - `arduino_uart`: `ARDUINO_UART_D0D1` or similar are available
        - `arduino_spi`: `ARDUINO_SPI_ISP` or similar are available
        - `arduino_i2c`: `ARDUINO_I2C_UNO` or similar are available
    - mechanical/electrical compatibility with specific form factors
      can now be expressed as features:
        - `aruino_shield_nano`: Arduino NANO compatible headers
        - `aruino_shield_uno`: Arduino UNO compatible headers
        - `aruino_shield_mega`: Arduino MEGA compatible headers
        - `aruino_shield_isp`: ISP header is available

This provides the groundwork to implement shield support as modules
that can rely on the I/O mappings, rather than having to provide a
configuration per board.
2023-06-26 17:24:07 +02:00

170 lines
3.8 KiB
C++

/*
* Copyright (C) 2015 Freie Universität Berlin
*
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License v2.1. See the file LICENSE in the top level directory for more
* details.
*/
/**
* @ingroup sys_arduino
* @{
*
* @file
* @brief Implementation of Arduino core functionality
*
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
*
* @}
*/
#include "arduino_board.h"
#include "assert.h"
#include "periph/adc.h"
#include "periph/gpio.h"
#include "periph/pwm.h"
#include "ztimer.h"
#include "arduino.hpp"
void pinMode(int pin, int mode)
{
if ((pin > ARDUINO_PIN_LAST) || (pin < 0) ||
!gpio_is_valid(arduino_pinmap[pin])) {
assert(0);
return;
}
gpio_mode_t m = GPIO_OUT;
if (mode == INPUT) {
m = GPIO_IN;
}
else if (mode == INPUT_PULLUP) {
m = GPIO_IN_PU;
}
gpio_init(arduino_pinmap[pin], m);
}
void digitalWrite(int pin, int state)
{
assert(gpio_is_valid(arduino_pinmap[pin]));
gpio_write(arduino_pinmap[pin], state);
}
int digitalRead(int pin)
{
assert(gpio_is_valid(arduino_pinmap[pin]));
if (gpio_read(arduino_pinmap[pin])) {
return HIGH;
}
else {
return LOW;
}
}
void delay(unsigned long msec)
{
ztimer_sleep(ZTIMER_MSEC, msec);
}
void delayMicroseconds(unsigned long usec)
{
ztimer_sleep(ZTIMER_USEC, usec);
}
unsigned long micros()
{
return ztimer_now(ZTIMER_USEC);
}
unsigned long millis()
{
return ztimer_now(ZTIMER_MSEC);
}
#if IS_USED(MODULE_PERIPH_ADC) && defined(ARDUINO_ANALOG_PIN_LAST)
int analogRead(int arduino_pin)
{
/*
* Bitfield for the state of the ADC-channels.
* 0: Not initialized
* 1: Successfully initialized
*/
static uint16_t adc_line_state;
#if ARDUINO_ANALOG_PIN_LAST > 15
# error "Implementation currently not compatible with more than 16 analog pins"
#endif
int adc_value;
/* Check if the ADC line is valid */
assert((arduino_pin >= 0) && (arduino_pin <= (int)ARDUINO_ANALOG_PIN_LAST));
/* Initialization of given ADC channel */
if (!(adc_line_state & (1UL << arduino_pin))) {
if (adc_init(arduino_analog_map[arduino_pin]) != 0) {
return -1;
}
/* The ADC channel is initialized */
adc_line_state |= (1 << arduino_pin);
}
/* Read the ADC channel */
adc_value = adc_sample(arduino_analog_map[arduino_pin], ADC_RES_10BIT);
return adc_value;
}
#endif
#if MODULE_PERIPH_PWM
static int _get_pwm_pin_idx(int pin)
{
for (uint8_t i = 0; i < ARRAY_SIZE(arduino_pwm_list); ++i) {
if (arduino_pwm_list[i].pin == pin) {
return i;
}
}
return -1;
}
void analogWrite(int pin, int value)
{
/*
* Bitfield for the state of the PWM devices.
* 0: Not initialized
* 1: Successfully initialized
*/
static uint8_t pwm_dev_state;
/* Clamp given value within bounds */
if (value < 0) {
value = 0;
}
if ((unsigned)value >= ARDUINO_PWM_STEPS) {
value = ARDUINO_PWM_STEPS - 1;
}
/* Check if the PWM pin is valid */
int pin_idx = _get_pwm_pin_idx(pin);
if (pin_idx == -1) {
/* Set to digital write if not a PWM pin */
pinMode(pin, OUTPUT);
return;
}
/* Initialization of given PWM pin */
if (!(pwm_dev_state & (1 << arduino_pwm_list[pin_idx].dev))) {
if (pwm_init(arduino_pwm_list[pin_idx].dev,
ARDUINO_PWM_MODE, ARDUINO_PWM_FREQU, ARDUINO_PWM_STEPS) == 0) {
return;
}
/* The PWM channel is initialized */
pwm_dev_state |= (1 << arduino_pwm_list[pin_idx].dev);
}
/* Write analog value */
pwm_set(arduino_pwm_list[pin_idx].dev, arduino_pwm_list[pin_idx].chan, value);
}
#endif /* MODULE_PERIPH_PWM */