2015-09-18 23:00:31 +02:00
|
|
|
/*
|
|
|
|
* 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>
|
|
|
|
*
|
|
|
|
* @}
|
|
|
|
*/
|
|
|
|
|
2023-06-23 15:42:08 +02:00
|
|
|
#include "arduino_board.h"
|
2020-10-27 18:55:27 +01:00
|
|
|
#include "assert.h"
|
2017-02-15 21:28:10 +01:00
|
|
|
#include "periph/adc.h"
|
2023-06-23 15:42:08 +02:00
|
|
|
#include "periph/gpio.h"
|
2019-10-20 17:28:29 +02:00
|
|
|
#include "periph/pwm.h"
|
2023-06-23 15:42:08 +02:00
|
|
|
#include "ztimer.h"
|
2015-09-18 23:00:31 +02:00
|
|
|
|
|
|
|
#include "arduino.hpp"
|
|
|
|
|
2016-02-20 17:22:39 +01:00
|
|
|
void pinMode(int pin, int mode)
|
2015-09-18 23:00:31 +02:00
|
|
|
{
|
2023-06-23 15:42:08 +02:00
|
|
|
if ((pin > ARDUINO_PIN_LAST) || (pin < 0) ||
|
|
|
|
!gpio_is_valid(arduino_pinmap[pin])) {
|
|
|
|
assert(0);
|
|
|
|
return;
|
|
|
|
}
|
2016-02-20 17:22:39 +01:00
|
|
|
gpio_mode_t m = GPIO_OUT;
|
2015-09-18 23:00:31 +02:00
|
|
|
|
2016-02-20 17:22:39 +01:00
|
|
|
if (mode == INPUT) {
|
|
|
|
m = GPIO_IN;
|
|
|
|
}
|
|
|
|
else if (mode == INPUT_PULLUP) {
|
|
|
|
m = GPIO_IN_PU;
|
|
|
|
}
|
2015-09-18 23:00:31 +02:00
|
|
|
|
2016-02-20 17:22:39 +01:00
|
|
|
gpio_init(arduino_pinmap[pin], m);
|
2015-09-18 23:00:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void digitalWrite(int pin, int state)
|
|
|
|
{
|
2021-12-27 11:37:57 +01:00
|
|
|
assert(gpio_is_valid(arduino_pinmap[pin]));
|
2015-09-18 23:00:31 +02:00
|
|
|
gpio_write(arduino_pinmap[pin], state);
|
|
|
|
}
|
|
|
|
|
|
|
|
int digitalRead(int pin)
|
|
|
|
{
|
2021-12-27 11:37:57 +01:00
|
|
|
assert(gpio_is_valid(arduino_pinmap[pin]));
|
2015-09-18 23:00:31 +02:00
|
|
|
if (gpio_read(arduino_pinmap[pin])) {
|
|
|
|
return HIGH;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return LOW;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-24 11:01:48 +02:00
|
|
|
void delay(unsigned long msec)
|
2015-09-18 23:00:31 +02:00
|
|
|
{
|
2020-10-27 18:55:27 +01:00
|
|
|
ztimer_sleep(ZTIMER_MSEC, msec);
|
2015-09-18 23:00:31 +02:00
|
|
|
}
|
2017-02-15 21:28:10 +01:00
|
|
|
|
2018-10-11 14:42:46 +02:00
|
|
|
void delayMicroseconds(unsigned long usec)
|
|
|
|
{
|
2020-10-27 18:55:27 +01:00
|
|
|
ztimer_sleep(ZTIMER_USEC, usec);
|
2018-10-11 14:42:46 +02:00
|
|
|
}
|
|
|
|
|
2018-10-12 17:40:37 +02:00
|
|
|
unsigned long micros()
|
2018-10-11 14:42:46 +02:00
|
|
|
{
|
2020-10-27 18:55:27 +01:00
|
|
|
return ztimer_now(ZTIMER_USEC);
|
2018-10-11 14:42:46 +02:00
|
|
|
}
|
|
|
|
|
2019-05-29 12:53:17 +02:00
|
|
|
unsigned long millis()
|
|
|
|
{
|
2020-10-27 18:55:27 +01:00
|
|
|
return ztimer_now(ZTIMER_MSEC);
|
2019-05-29 12:53:17 +02:00
|
|
|
}
|
|
|
|
|
2023-06-23 15:42:08 +02:00
|
|
|
#if IS_USED(MODULE_PERIPH_ADC) && defined(ARDUINO_ANALOG_PIN_LAST)
|
2017-02-15 21:28:10 +01:00
|
|
|
int analogRead(int arduino_pin)
|
|
|
|
{
|
2019-08-05 21:33:43 +02:00
|
|
|
/*
|
|
|
|
* Bitfield for the state of the ADC-channels.
|
|
|
|
* 0: Not initialized
|
|
|
|
* 1: Successfully initialized
|
|
|
|
*/
|
|
|
|
static uint16_t adc_line_state;
|
2023-06-23 15:42:08 +02:00
|
|
|
#if ARDUINO_ANALOG_PIN_LAST > 15
|
|
|
|
# error "Implementation currently not compatible with more than 16 analog pins"
|
|
|
|
#endif
|
2017-02-15 21:28:10 +01:00
|
|
|
int adc_value;
|
|
|
|
|
|
|
|
/* Check if the ADC line is valid */
|
2023-06-23 15:42:08 +02:00
|
|
|
assert((arduino_pin >= 0) && (arduino_pin <= (int)ARDUINO_ANALOG_PIN_LAST));
|
2017-02-15 21:28:10 +01:00
|
|
|
|
|
|
|
/* Initialization of given ADC channel */
|
2023-06-23 15:42:08 +02:00
|
|
|
if (!(adc_line_state & (1UL << arduino_pin))) {
|
2017-02-15 21:28:10 +01:00
|
|
|
if (adc_init(arduino_analog_map[arduino_pin]) != 0) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
/* The ADC channel is initialized */
|
2019-08-05 21:33:43 +02:00
|
|
|
adc_line_state |= (1 << arduino_pin);
|
2017-02-15 21:28:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Read the ADC channel */
|
|
|
|
adc_value = adc_sample(arduino_analog_map[arduino_pin], ADC_RES_10BIT);
|
|
|
|
|
|
|
|
return adc_value;
|
|
|
|
}
|
2019-10-08 10:26:23 +02:00
|
|
|
#endif
|
2019-10-20 17:28:29 +02:00
|
|
|
|
|
|
|
#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 */
|