Revert "add gyro. Clock speed up to 500 Hz."
This reverts commit 2d88948c99.
This commit is contained in:
parent
ed4defd0a0
commit
e249cd0f23
75 changed files with 443 additions and 17479 deletions
|
|
@ -1,203 +0,0 @@
|
|||
/*
|
||||
Arduino.h - Main include file for the Arduino SDK
|
||||
Copyright (c) 2005-2013 Arduino Team. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef Arduino_h
|
||||
#define Arduino_h
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "esp_arduino_version.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "esp32-hal.h"
|
||||
#include "esp8266-compat.h"
|
||||
#include "soc/gpio_reg.h"
|
||||
|
||||
#include "stdlib_noniso.h"
|
||||
#include "binary.h"
|
||||
|
||||
#define PI 3.1415926535897932384626433832795
|
||||
#define HALF_PI 1.5707963267948966192313216916398
|
||||
#define TWO_PI 6.283185307179586476925286766559
|
||||
#define DEG_TO_RAD 0.017453292519943295769236907684886
|
||||
#define RAD_TO_DEG 57.295779513082320876798154814105
|
||||
#define EULER 2.718281828459045235360287471352
|
||||
|
||||
#define SERIAL 0x0
|
||||
#define DISPLAY 0x1
|
||||
|
||||
#define LSBFIRST 0
|
||||
#define MSBFIRST 1
|
||||
|
||||
//Interrupt Modes
|
||||
#define RISING 0x01
|
||||
#define FALLING 0x02
|
||||
#define CHANGE 0x03
|
||||
#define ONLOW 0x04
|
||||
#define ONHIGH 0x05
|
||||
#define ONLOW_WE 0x0C
|
||||
#define ONHIGH_WE 0x0D
|
||||
|
||||
#define DEFAULT 1
|
||||
#define EXTERNAL 0
|
||||
|
||||
#ifndef __STRINGIFY
|
||||
#define __STRINGIFY(a) #a
|
||||
#endif
|
||||
|
||||
#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))
|
||||
#define radians(deg) ((deg)*DEG_TO_RAD)
|
||||
#define degrees(rad) ((rad)*RAD_TO_DEG)
|
||||
#define sq(x) ((x)*(x))
|
||||
|
||||
#define sei()
|
||||
#define cli()
|
||||
#define interrupts() sei()
|
||||
#define noInterrupts() cli()
|
||||
|
||||
#define clockCyclesPerMicrosecond() ( (long int)getCpuFrequencyMhz() )
|
||||
#define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() )
|
||||
#define microsecondsToClockCycles(a) ( (a) * clockCyclesPerMicrosecond() )
|
||||
|
||||
#define lowByte(w) ((uint8_t) ((w) & 0xff))
|
||||
#define highByte(w) ((uint8_t) ((w) >> 8))
|
||||
|
||||
#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
|
||||
#define bitSet(value, bit) ((value) |= (1UL << (bit)))
|
||||
#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
|
||||
#define bitWrite(value, bit, bitvalue) ((bitvalue) ? bitSet(value, bit) : bitClear(value, bit))
|
||||
|
||||
// avr-libc defines _NOP() since 1.6.2
|
||||
#ifndef _NOP
|
||||
#define _NOP() do { __asm__ volatile ("nop"); } while (0)
|
||||
#endif
|
||||
|
||||
#define bit(b) (1UL << (b))
|
||||
#define _BV(b) (1UL << (b))
|
||||
|
||||
#define digitalPinToTimer(pin) (0)
|
||||
#define analogInPinToBit(P) (P)
|
||||
#if SOC_GPIO_PIN_COUNT <= 32
|
||||
#define digitalPinToPort(pin) (0)
|
||||
#define digitalPinToBitMask(pin) (1UL << (pin))
|
||||
#define portOutputRegister(port) ((volatile uint32_t*)GPIO_OUT_REG)
|
||||
#define portInputRegister(port) ((volatile uint32_t*)GPIO_IN_REG)
|
||||
#define portModeRegister(port) ((volatile uint32_t*)GPIO_ENABLE_REG)
|
||||
#elif SOC_GPIO_PIN_COUNT <= 64
|
||||
#define digitalPinToPort(pin) (((pin)>31)?1:0)
|
||||
#define digitalPinToBitMask(pin) (1UL << (((pin)>31)?((pin)-32):(pin)))
|
||||
#define portOutputRegister(port) ((volatile uint32_t*)((port)?GPIO_OUT1_REG:GPIO_OUT_REG))
|
||||
#define portInputRegister(port) ((volatile uint32_t*)((port)?GPIO_IN1_REG:GPIO_IN_REG))
|
||||
#define portModeRegister(port) ((volatile uint32_t*)((port)?GPIO_ENABLE1_REG:GPIO_ENABLE_REG))
|
||||
#else
|
||||
#error SOC_GPIO_PIN_COUNT > 64 not implemented
|
||||
#endif
|
||||
|
||||
#define NOT_A_PIN -1
|
||||
#define NOT_A_PORT -1
|
||||
#define NOT_AN_INTERRUPT -1
|
||||
#define NOT_ON_TIMER 0
|
||||
|
||||
typedef bool boolean;
|
||||
typedef uint8_t byte;
|
||||
typedef unsigned int word;
|
||||
|
||||
#ifdef __cplusplus
|
||||
void setup(void);
|
||||
void loop(void);
|
||||
|
||||
long random(long, long);
|
||||
#endif
|
||||
void randomSeed(unsigned long);
|
||||
long map(long, long, long, long, long);
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void init(void);
|
||||
void initVariant(void);
|
||||
void initArduino(void);
|
||||
|
||||
unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout);
|
||||
unsigned long pulseInLong(uint8_t pin, uint8_t state, unsigned long timeout);
|
||||
|
||||
uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder);
|
||||
void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
#include "WCharacter.h"
|
||||
#include "WString.h"
|
||||
#include "Stream.h"
|
||||
#include "Printable.h"
|
||||
#include "Print.h"
|
||||
#include "IPAddress.h"
|
||||
#include "Client.h"
|
||||
#include "Server.h"
|
||||
#include "Udp.h"
|
||||
#include "HardwareSerial.h"
|
||||
#include "Esp.h"
|
||||
|
||||
using std::abs;
|
||||
using std::isinf;
|
||||
using std::isnan;
|
||||
using std::max;
|
||||
using std::min;
|
||||
using ::round;
|
||||
|
||||
uint16_t makeWord(uint16_t w);
|
||||
uint16_t makeWord(uint8_t h, uint8_t l);
|
||||
|
||||
#define word(...) makeWord(__VA_ARGS__)
|
||||
|
||||
size_t getArduinoLoopTaskStackSize(void);
|
||||
#define SET_LOOP_TASK_STACK_SIZE(sz) size_t getArduinoLoopTaskStackSize() { return sz;}
|
||||
|
||||
unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L);
|
||||
unsigned long pulseInLong(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L);
|
||||
|
||||
extern "C" bool getLocalTime(struct tm * info, uint32_t ms = 5000);
|
||||
extern "C" void configTime(long gmtOffset_sec, int daylightOffset_sec,
|
||||
const char* server1, const char* server2 = nullptr, const char* server3 = nullptr);
|
||||
extern "C" void configTzTime(const char* tz,
|
||||
const char* server1, const char* server2 = nullptr, const char* server3 = nullptr);
|
||||
|
||||
// WMath prototypes
|
||||
long random(long);
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#define _min(a,b) ((a)<(b)?(a):(b))
|
||||
#define _max(a,b) ((a)>(b)?(a):(b))
|
||||
|
||||
#include "pins_arduino.h"
|
||||
|
||||
#endif /* _ESP32_CORE_ARDUINO_H_ */
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
/*
|
||||
Client.h - Base class that provides Client
|
||||
Copyright (c) 2011 Adrian McEwen. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef client_h
|
||||
#define client_h
|
||||
#include "Print.h"
|
||||
#include "Stream.h"
|
||||
#include "IPAddress.h"
|
||||
|
||||
class Client: public Stream
|
||||
{
|
||||
public:
|
||||
virtual int connect(IPAddress ip, uint16_t port) =0;
|
||||
virtual int connect(const char *host, uint16_t port) =0;
|
||||
virtual size_t write(uint8_t) =0;
|
||||
virtual size_t write(const uint8_t *buf, size_t size) =0;
|
||||
virtual int available() = 0;
|
||||
virtual int read() = 0;
|
||||
virtual int read(uint8_t *buf, size_t size) = 0;
|
||||
virtual int peek() = 0;
|
||||
virtual void flush() = 0;
|
||||
virtual void stop() = 0;
|
||||
virtual uint8_t connected() = 0;
|
||||
virtual operator bool() = 0;
|
||||
protected:
|
||||
uint8_t* rawIPAddress(IPAddress& addr)
|
||||
{
|
||||
return addr.raw_address();
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
119
arduino/Esp.h
119
arduino/Esp.h
|
|
@ -1,119 +0,0 @@
|
|||
/*
|
||||
Esp.h - ESP31B-specific APIs
|
||||
Copyright (c) 2015 Ivan Grokhotkov. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef ESP_H
|
||||
#define ESP_H
|
||||
|
||||
#include "Arduino.h"
|
||||
#include <esp_partition.h>
|
||||
#include <hal/cpu_hal.h>
|
||||
|
||||
/**
|
||||
* AVR macros for WDT managment
|
||||
*/
|
||||
typedef enum {
|
||||
WDTO_0MS = 0, //!< WDTO_0MS
|
||||
WDTO_15MS = 15, //!< WDTO_15MS
|
||||
WDTO_30MS = 30, //!< WDTO_30MS
|
||||
WDTO_60MS = 60, //!< WDTO_60MS
|
||||
WDTO_120MS = 120, //!< WDTO_120MS
|
||||
WDTO_250MS = 250, //!< WDTO_250MS
|
||||
WDTO_500MS = 500, //!< WDTO_500MS
|
||||
WDTO_1S = 1000,//!< WDTO_1S
|
||||
WDTO_2S = 2000,//!< WDTO_2S
|
||||
WDTO_4S = 4000,//!< WDTO_4S
|
||||
WDTO_8S = 8000 //!< WDTO_8S
|
||||
} WDTO_t;
|
||||
|
||||
|
||||
typedef enum {
|
||||
FM_QIO = 0x00,
|
||||
FM_QOUT = 0x01,
|
||||
FM_DIO = 0x02,
|
||||
FM_DOUT = 0x03,
|
||||
FM_FAST_READ = 0x04,
|
||||
FM_SLOW_READ = 0x05,
|
||||
FM_UNKNOWN = 0xff
|
||||
} FlashMode_t;
|
||||
|
||||
typedef enum {
|
||||
SKETCH_SIZE_TOTAL = 0,
|
||||
SKETCH_SIZE_FREE = 1
|
||||
} sketchSize_t;
|
||||
|
||||
class EspClass
|
||||
{
|
||||
public:
|
||||
EspClass() {}
|
||||
~EspClass() {}
|
||||
void restart();
|
||||
|
||||
//Internal RAM
|
||||
uint32_t getHeapSize(); //total heap size
|
||||
uint32_t getFreeHeap(); //available heap
|
||||
uint32_t getMinFreeHeap(); //lowest level of free heap since boot
|
||||
uint32_t getMaxAllocHeap(); //largest block of heap that can be allocated at once
|
||||
|
||||
//SPI RAM
|
||||
uint32_t getPsramSize();
|
||||
uint32_t getFreePsram();
|
||||
uint32_t getMinFreePsram();
|
||||
uint32_t getMaxAllocPsram();
|
||||
|
||||
uint8_t getChipRevision();
|
||||
const char * getChipModel();
|
||||
uint8_t getChipCores();
|
||||
uint32_t getCpuFreqMHz(){ return getCpuFrequencyMhz(); }
|
||||
inline uint32_t getCycleCount() __attribute__((always_inline));
|
||||
const char * getSdkVersion();
|
||||
|
||||
void deepSleep(uint32_t time_us);
|
||||
|
||||
uint32_t getFlashChipSize();
|
||||
uint32_t getFlashChipSpeed();
|
||||
FlashMode_t getFlashChipMode();
|
||||
|
||||
uint32_t magicFlashChipSize(uint8_t byte);
|
||||
uint32_t magicFlashChipSpeed(uint8_t byte);
|
||||
FlashMode_t magicFlashChipMode(uint8_t byte);
|
||||
|
||||
uint32_t getSketchSize();
|
||||
String getSketchMD5();
|
||||
uint32_t getFreeSketchSpace();
|
||||
|
||||
bool flashEraseSector(uint32_t sector);
|
||||
bool flashWrite(uint32_t offset, uint32_t *data, size_t size);
|
||||
bool flashRead(uint32_t offset, uint32_t *data, size_t size);
|
||||
|
||||
bool partitionEraseRange(const esp_partition_t *partition, uint32_t offset, size_t size);
|
||||
bool partitionWrite(const esp_partition_t *partition, uint32_t offset, uint32_t *data, size_t size);
|
||||
bool partitionRead(const esp_partition_t *partition, uint32_t offset, uint32_t *data, size_t size);
|
||||
|
||||
uint64_t getEfuseMac();
|
||||
|
||||
};
|
||||
|
||||
uint32_t ARDUINO_ISR_ATTR EspClass::getCycleCount()
|
||||
{
|
||||
return esp_cpu_get_cycle_count();
|
||||
}
|
||||
|
||||
extern EspClass ESP;
|
||||
|
||||
#endif //ESP_H
|
||||
107
arduino/HWCDC.h
107
arduino/HWCDC.h
|
|
@ -1,107 +0,0 @@
|
|||
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// 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.
|
||||
#pragma once
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32C3
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "esp_event.h"
|
||||
#include "Stream.h"
|
||||
|
||||
ESP_EVENT_DECLARE_BASE(ARDUINO_HW_CDC_EVENTS);
|
||||
|
||||
typedef enum {
|
||||
ARDUINO_HW_CDC_ANY_EVENT = ESP_EVENT_ANY_ID,
|
||||
ARDUINO_HW_CDC_CONNECTED_EVENT = 0,
|
||||
ARDUINO_HW_CDC_BUS_RESET_EVENT,
|
||||
ARDUINO_HW_CDC_RX_EVENT,
|
||||
ARDUINO_HW_CDC_TX_EVENT,
|
||||
ARDUINO_HW_CDC_MAX_EVENT,
|
||||
} arduino_hw_cdc_event_t;
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
size_t len;
|
||||
} rx;
|
||||
struct {
|
||||
size_t len;
|
||||
} tx;
|
||||
} arduino_hw_cdc_event_data_t;
|
||||
|
||||
class HWCDC: public Stream
|
||||
{
|
||||
public:
|
||||
HWCDC();
|
||||
~HWCDC();
|
||||
|
||||
void onEvent(esp_event_handler_t callback);
|
||||
void onEvent(arduino_hw_cdc_event_t event, esp_event_handler_t callback);
|
||||
|
||||
size_t setRxBufferSize(size_t);
|
||||
size_t setTxBufferSize(size_t);
|
||||
void setTxTimeoutMs(uint32_t timeout);
|
||||
void begin(unsigned long baud=0);
|
||||
void end();
|
||||
|
||||
int available(void);
|
||||
int availableForWrite(void);
|
||||
int peek(void);
|
||||
int read(void);
|
||||
size_t read(uint8_t *buffer, size_t size);
|
||||
size_t write(uint8_t);
|
||||
size_t write(const uint8_t *buffer, size_t size);
|
||||
void flush(void);
|
||||
|
||||
inline size_t read(char * buffer, size_t size)
|
||||
{
|
||||
return read((uint8_t*) buffer, size);
|
||||
}
|
||||
inline size_t write(const char * buffer, size_t size)
|
||||
{
|
||||
return write((uint8_t*) buffer, size);
|
||||
}
|
||||
inline size_t write(const char * s)
|
||||
{
|
||||
return write((uint8_t*) s, strlen(s));
|
||||
}
|
||||
inline size_t write(unsigned long n)
|
||||
{
|
||||
return write((uint8_t) n);
|
||||
}
|
||||
inline size_t write(long n)
|
||||
{
|
||||
return write((uint8_t) n);
|
||||
}
|
||||
inline size_t write(unsigned int n)
|
||||
{
|
||||
return write((uint8_t) n);
|
||||
}
|
||||
inline size_t write(int n)
|
||||
{
|
||||
return write((uint8_t) n);
|
||||
}
|
||||
operator bool() const;
|
||||
void setDebugOutput(bool);
|
||||
uint32_t baudRate(){return 115200;}
|
||||
|
||||
};
|
||||
|
||||
#if ARDUINO_HW_CDC_ON_BOOT //Serial used for USB CDC
|
||||
extern HWCDC Serial;
|
||||
#else
|
||||
extern HWCDC USBSerial;
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_IDF_TARGET_ESP32C3 */
|
||||
|
|
@ -1,554 +0,0 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <ctime>
|
||||
|
||||
#include "pins_arduino.h"
|
||||
#include "io_pin_remap.h"
|
||||
#include "HardwareSerial.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "driver/uart.h"
|
||||
#include "freertos/queue.h"
|
||||
|
||||
#ifndef ARDUINO_SERIAL_EVENT_TASK_STACK_SIZE
|
||||
#define ARDUINO_SERIAL_EVENT_TASK_STACK_SIZE 2048
|
||||
#endif
|
||||
|
||||
#ifndef ARDUINO_SERIAL_EVENT_TASK_PRIORITY
|
||||
#define ARDUINO_SERIAL_EVENT_TASK_PRIORITY (configMAX_PRIORITIES - 1)
|
||||
#endif
|
||||
|
||||
#ifndef ARDUINO_SERIAL_EVENT_TASK_RUNNING_CORE
|
||||
#define ARDUINO_SERIAL_EVENT_TASK_RUNNING_CORE -1
|
||||
#endif
|
||||
|
||||
void serialEvent(void) __attribute__((weak));
|
||||
void serialEvent(void) {}
|
||||
|
||||
#if SOC_UART_NUM > 1
|
||||
void serialEvent1(void) __attribute__((weak));
|
||||
void serialEvent1(void) {}
|
||||
#endif /* SOC_UART_NUM > 1 */
|
||||
|
||||
#if SOC_UART_NUM > 2
|
||||
void serialEvent2(void) __attribute__((weak));
|
||||
void serialEvent2(void) {}
|
||||
#endif /* SOC_UART_NUM > 2 */
|
||||
|
||||
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL)
|
||||
// There is always Seria0 for UART0
|
||||
HardwareSerial Serial0(0);
|
||||
#if SOC_UART_NUM > 1
|
||||
HardwareSerial Serial1(1);
|
||||
#endif
|
||||
#if SOC_UART_NUM > 2
|
||||
HardwareSerial Serial2(2);
|
||||
#endif
|
||||
|
||||
#if HWCDC_SERIAL_IS_DEFINED == 1 // Hardware JTAG CDC Event
|
||||
extern void HWCDCSerialEvent(void) __attribute__((weak));
|
||||
void HWCDCSerialEvent(void) {}
|
||||
#endif
|
||||
|
||||
#if USB_SERIAL_IS_DEFINED == 1 // Native USB CDC Event
|
||||
// Used by Hardware Serial for USB CDC events
|
||||
extern void USBSerialEvent(void) __attribute__((weak));
|
||||
void USBSerialEvent(void) {}
|
||||
#endif
|
||||
|
||||
void serialEventRun(void) {
|
||||
#if HWCDC_SERIAL_IS_DEFINED == 1 // Hardware JTAG CDC Event
|
||||
if (HWCDCSerial.available()) {
|
||||
HWCDCSerialEvent();
|
||||
}
|
||||
#endif
|
||||
#if USB_SERIAL_IS_DEFINED == 1 // Native USB CDC Event
|
||||
if (USBSerial.available()) {
|
||||
USBSerialEvent();
|
||||
}
|
||||
#endif
|
||||
// UART0 is default serialEvent()
|
||||
if (Serial0.available()) {
|
||||
serialEvent();
|
||||
}
|
||||
#if SOC_UART_NUM > 1
|
||||
if (Serial1.available()) {
|
||||
serialEvent1();
|
||||
}
|
||||
#endif
|
||||
#if SOC_UART_NUM > 2
|
||||
if (Serial2.available()) {
|
||||
serialEvent2();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
#define HSERIAL_MUTEX_LOCK() \
|
||||
do { \
|
||||
} while (xSemaphoreTake(_lock, portMAX_DELAY) != pdPASS)
|
||||
#define HSERIAL_MUTEX_UNLOCK() xSemaphoreGive(_lock)
|
||||
#else
|
||||
#define HSERIAL_MUTEX_LOCK()
|
||||
#define HSERIAL_MUTEX_UNLOCK()
|
||||
#endif
|
||||
|
||||
HardwareSerial::HardwareSerial(uint8_t uart_nr)
|
||||
: _uart_nr(uart_nr), _uart(NULL), _rxBufferSize(256), _txBufferSize(0), _onReceiveCB(NULL), _onReceiveErrorCB(NULL), _onReceiveTimeout(false), _rxTimeout(1),
|
||||
_rxFIFOFull(0), _eventTask(NULL)
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
,
|
||||
_lock(NULL)
|
||||
#endif
|
||||
{
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
if (_lock == NULL) {
|
||||
_lock = xSemaphoreCreateMutex();
|
||||
if (_lock == NULL) {
|
||||
log_e("xSemaphoreCreateMutex failed");
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// set deinit function in the Peripheral Manager
|
||||
uart_init_PeriMan();
|
||||
}
|
||||
|
||||
HardwareSerial::~HardwareSerial() {
|
||||
end(); // explicit Full UART termination
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
if (_lock != NULL) {
|
||||
vSemaphoreDelete(_lock);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void HardwareSerial::_createEventTask(void *args) {
|
||||
// Creating UART event Task
|
||||
xTaskCreateUniversal(
|
||||
_uartEventTask, "uart_event_task", ARDUINO_SERIAL_EVENT_TASK_STACK_SIZE, this, ARDUINO_SERIAL_EVENT_TASK_PRIORITY, &_eventTask,
|
||||
ARDUINO_SERIAL_EVENT_TASK_RUNNING_CORE
|
||||
);
|
||||
if (_eventTask == NULL) {
|
||||
log_e(" -- UART%d Event Task not Created!", _uart_nr);
|
||||
}
|
||||
}
|
||||
|
||||
void HardwareSerial::_destroyEventTask(void) {
|
||||
if (_eventTask != NULL) {
|
||||
vTaskDelete(_eventTask);
|
||||
_eventTask = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void HardwareSerial::onReceiveError(OnReceiveErrorCb function) {
|
||||
HSERIAL_MUTEX_LOCK();
|
||||
// function may be NULL to cancel onReceive() from its respective task
|
||||
_onReceiveErrorCB = function;
|
||||
// this can be called after Serial.begin(), therefore it shall create the event task
|
||||
if (function != NULL && _uart != NULL && _eventTask == NULL) {
|
||||
_createEventTask(this);
|
||||
}
|
||||
HSERIAL_MUTEX_UNLOCK();
|
||||
}
|
||||
|
||||
void HardwareSerial::onReceive(OnReceiveCb function, bool onlyOnTimeout) {
|
||||
HSERIAL_MUTEX_LOCK();
|
||||
// function may be NULL to cancel onReceive() from its respective task
|
||||
_onReceiveCB = function;
|
||||
|
||||
// setting the callback to NULL will just disable it
|
||||
if (_onReceiveCB != NULL) {
|
||||
// When Rx timeout is Zero (disabled), there is only one possible option that is callback when FIFO reaches 120 bytes
|
||||
_onReceiveTimeout = _rxTimeout > 0 ? onlyOnTimeout : false;
|
||||
|
||||
// in case that onReceive() shall work only with RX Timeout, FIFO shall be high
|
||||
// this is a work around for an IDF issue with events and low FIFO Full value (< 3)
|
||||
if (_onReceiveTimeout) {
|
||||
uartSetRxFIFOFull(_uart, 120);
|
||||
log_w("OnReceive is set to Timeout only, thus FIFO Full is now 120 bytes.");
|
||||
}
|
||||
|
||||
// this method can be called after Serial.begin(), therefore it shall create the event task
|
||||
if (_uart != NULL && _eventTask == NULL) {
|
||||
_createEventTask(this); // Create event task
|
||||
}
|
||||
}
|
||||
HSERIAL_MUTEX_UNLOCK();
|
||||
}
|
||||
|
||||
// This function allow the user to define how many bytes will trigger an Interrupt that will copy RX FIFO to the internal RX Ringbuffer
|
||||
// ISR will also move data from FIFO to RX Ringbuffer after a RX Timeout defined in HardwareSerial::setRxTimeout(uint8_t symbols_timeout)
|
||||
// A low value of FIFO Full bytes will consume more CPU time within the ISR
|
||||
// A high value of FIFO Full bytes will make the application wait longer to have byte available for the Stkech in a streaming scenario
|
||||
// Both RX FIFO Full and RX Timeout may affect when onReceive() will be called
|
||||
bool HardwareSerial::setRxFIFOFull(uint8_t fifoBytes) {
|
||||
HSERIAL_MUTEX_LOCK();
|
||||
// in case that onReceive() shall work only with RX Timeout, FIFO shall be high
|
||||
// this is a work around for an IDF issue with events and low FIFO Full value (< 3)
|
||||
if (_onReceiveCB != NULL && _onReceiveTimeout) {
|
||||
fifoBytes = 120;
|
||||
log_w("OnReceive is set to Timeout only, thus FIFO Full is now 120 bytes.");
|
||||
}
|
||||
bool retCode = uartSetRxFIFOFull(_uart, fifoBytes); // Set new timeout
|
||||
if (fifoBytes > 0 && fifoBytes < SOC_UART_FIFO_LEN - 1) {
|
||||
_rxFIFOFull = fifoBytes;
|
||||
}
|
||||
HSERIAL_MUTEX_UNLOCK();
|
||||
return retCode;
|
||||
}
|
||||
|
||||
// timeout is calculates in time to receive UART symbols at the UART baudrate.
|
||||
// the estimation is about 11 bits per symbol (SERIAL_8N1)
|
||||
bool HardwareSerial::setRxTimeout(uint8_t symbols_timeout) {
|
||||
HSERIAL_MUTEX_LOCK();
|
||||
|
||||
// Zero disables timeout, thus, onReceive callback will only be called when RX FIFO reaches 120 bytes
|
||||
// Any non-zero value will activate onReceive callback based on UART baudrate with about 11 bits per symbol
|
||||
_rxTimeout = symbols_timeout;
|
||||
if (!symbols_timeout) {
|
||||
_onReceiveTimeout = false; // only when RX timeout is disabled, we also must disable this flag
|
||||
}
|
||||
|
||||
bool retCode = uartSetRxTimeout(_uart, _rxTimeout); // Set new timeout
|
||||
|
||||
HSERIAL_MUTEX_UNLOCK();
|
||||
return retCode;
|
||||
}
|
||||
|
||||
void HardwareSerial::eventQueueReset() {
|
||||
QueueHandle_t uartEventQueue = NULL;
|
||||
if (_uart == NULL) {
|
||||
return;
|
||||
}
|
||||
uartGetEventQueue(_uart, &uartEventQueue);
|
||||
if (uartEventQueue != NULL) {
|
||||
xQueueReset(uartEventQueue);
|
||||
}
|
||||
}
|
||||
|
||||
void HardwareSerial::_uartEventTask(void *args) {
|
||||
HardwareSerial *uart = (HardwareSerial *)args;
|
||||
uart_event_t event;
|
||||
QueueHandle_t uartEventQueue = NULL;
|
||||
uartGetEventQueue(uart->_uart, &uartEventQueue);
|
||||
if (uartEventQueue != NULL) {
|
||||
for (;;) {
|
||||
//Waiting for UART event.
|
||||
if (xQueueReceive(uartEventQueue, (void *)&event, (TickType_t)portMAX_DELAY)) {
|
||||
hardwareSerial_error_t currentErr = UART_NO_ERROR;
|
||||
switch (event.type) {
|
||||
case UART_DATA:
|
||||
if (uart->_onReceiveCB && uart->available() > 0 && ((uart->_onReceiveTimeout && event.timeout_flag) || !uart->_onReceiveTimeout)) {
|
||||
uart->_onReceiveCB();
|
||||
}
|
||||
break;
|
||||
case UART_FIFO_OVF:
|
||||
log_w("UART%d FIFO Overflow. Consider adding Hardware Flow Control to your Application.", uart->_uart_nr);
|
||||
currentErr = UART_FIFO_OVF_ERROR;
|
||||
break;
|
||||
case UART_BUFFER_FULL:
|
||||
log_w("UART%d Buffer Full. Consider increasing your buffer size of your Application.", uart->_uart_nr);
|
||||
currentErr = UART_BUFFER_FULL_ERROR;
|
||||
break;
|
||||
case UART_BREAK:
|
||||
log_v("UART%d RX break.", uart->_uart_nr);
|
||||
currentErr = UART_BREAK_ERROR;
|
||||
break;
|
||||
case UART_PARITY_ERR:
|
||||
log_v("UART%d parity error.", uart->_uart_nr);
|
||||
currentErr = UART_PARITY_ERROR;
|
||||
break;
|
||||
case UART_FRAME_ERR:
|
||||
log_v("UART%d frame error.", uart->_uart_nr);
|
||||
currentErr = UART_FRAME_ERROR;
|
||||
break;
|
||||
default: log_v("UART%d unknown event type %d.", uart->_uart_nr, event.type); break;
|
||||
}
|
||||
if (currentErr != UART_NO_ERROR) {
|
||||
if (uart->_onReceiveErrorCB) {
|
||||
uart->_onReceiveErrorCB(currentErr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, int8_t txPin, bool invert, unsigned long timeout_ms, uint8_t rxfifo_full_thrhd) {
|
||||
if (_uart_nr >= SOC_UART_NUM) {
|
||||
log_e("Serial number is invalid, please use a number from 0 to %u", SOC_UART_NUM - 1);
|
||||
return;
|
||||
}
|
||||
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
if (_lock == NULL) {
|
||||
log_e("MUTEX Lock failed. Can't begin.");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
HSERIAL_MUTEX_LOCK();
|
||||
// First Time or after end() --> set default Pins
|
||||
if (!uartIsDriverInstalled(_uart)) {
|
||||
// get previously used RX/TX pins, if any.
|
||||
int8_t _rxPin = uart_get_RxPin(_uart_nr);
|
||||
int8_t _txPin = uart_get_TxPin(_uart_nr);
|
||||
switch (_uart_nr) {
|
||||
case UART_NUM_0:
|
||||
if (rxPin < 0 && txPin < 0) {
|
||||
// do not change RX0/TX0 if it has already been set before
|
||||
rxPin = _rxPin < 0 ? (int8_t)SOC_RX0 : _rxPin;
|
||||
txPin = _txPin < 0 ? (int8_t)SOC_TX0 : _txPin;
|
||||
}
|
||||
break;
|
||||
#if SOC_UART_NUM > 1 // may save some flash bytes...
|
||||
case UART_NUM_1:
|
||||
if (rxPin < 0 && txPin < 0) {
|
||||
// do not change RX1/TX1 if it has already been set before
|
||||
rxPin = _rxPin < 0 ? (int8_t)RX1 : _rxPin;
|
||||
txPin = _txPin < 0 ? (int8_t)TX1 : _txPin;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#if SOC_UART_NUM > 2 // may save some flash bytes...
|
||||
case UART_NUM_2:
|
||||
if (rxPin < 0 && txPin < 0) {
|
||||
// do not change RX2/TX2 if it has already been set before
|
||||
rxPin = _rxPin < 0 ? (int8_t)RX2 : _rxPin;
|
||||
txPin = _txPin < 0 ? (int8_t)TX2 : _txPin;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// map logical pins to GPIO numbers
|
||||
rxPin = digitalPinToGPIONumber(rxPin);
|
||||
txPin = digitalPinToGPIONumber(txPin);
|
||||
// IDF UART driver keeps Pin setting on restarting. Negative Pin number will keep it unmodified.
|
||||
// it will detach previous UART attached pins
|
||||
|
||||
// indicates that uartbegin() has to initialize a new IDF driver
|
||||
if (_testUartBegin(_uart_nr, baud ? baud : 9600, config, rxPin, txPin, _rxBufferSize, _txBufferSize, invert, rxfifo_full_thrhd)) {
|
||||
_destroyEventTask(); // when IDF uart driver must be restarted, _eventTask must finish too
|
||||
}
|
||||
|
||||
// IDF UART driver keeps Pin setting on restarting. Negative Pin number will keep it unmodified.
|
||||
// it will detach previous UART attached pins
|
||||
_uart = uartBegin(_uart_nr, baud ? baud : 9600, config, rxPin, txPin, _rxBufferSize, _txBufferSize, invert, rxfifo_full_thrhd);
|
||||
if (_uart == NULL) {
|
||||
log_e("UART driver failed to start. Please check the logs.");
|
||||
HSERIAL_MUTEX_UNLOCK();
|
||||
return;
|
||||
}
|
||||
if (!baud) {
|
||||
// using baud rate as zero, forces it to try to detect the current baud rate in place
|
||||
uartStartDetectBaudrate(_uart);
|
||||
time_t startMillis = millis();
|
||||
unsigned long detectedBaudRate = 0;
|
||||
while (millis() - startMillis < timeout_ms && !(detectedBaudRate = uartDetectBaudrate(_uart))) {
|
||||
yield();
|
||||
}
|
||||
|
||||
if (detectedBaudRate) {
|
||||
delay(100); // Give some time...
|
||||
_uart = uartBegin(_uart_nr, detectedBaudRate, config, rxPin, txPin, _rxBufferSize, _txBufferSize, invert, rxfifo_full_thrhd);
|
||||
if (_uart == NULL) {
|
||||
log_e("UART driver failed to start. Please check the logs.");
|
||||
HSERIAL_MUTEX_UNLOCK();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
log_e("Could not detect baudrate. Serial data at the port must be present within the timeout for detection to be possible");
|
||||
_uart = NULL;
|
||||
}
|
||||
}
|
||||
// create a task to deal with Serial Events when, for example, calling begin() twice to change the baudrate,
|
||||
// or when setting the callback before calling begin()
|
||||
if (_uart != NULL && (_onReceiveCB != NULL || _onReceiveErrorCB != NULL) && _eventTask == NULL) {
|
||||
_createEventTask(this);
|
||||
}
|
||||
|
||||
// Set UART RX timeout
|
||||
uartSetRxTimeout(_uart, _rxTimeout);
|
||||
|
||||
// Set UART FIFO Full depending on the baud rate.
|
||||
// Lower baud rates will force to emulate byte-by-byte reading
|
||||
// Higher baud rates will keep IDF default of 120 bytes for FIFO FULL Interrupt
|
||||
// It can also be changed by the application at any time
|
||||
if (!_rxFIFOFull) { // it has not being changed before calling begin()
|
||||
// set a default FIFO Full value for the IDF driver
|
||||
uint8_t fifoFull = 1;
|
||||
if (baud > 57600 || (_onReceiveCB != NULL && _onReceiveTimeout)) {
|
||||
fifoFull = 120;
|
||||
}
|
||||
uartSetRxFIFOFull(_uart, fifoFull);
|
||||
_rxFIFOFull = fifoFull;
|
||||
}
|
||||
|
||||
HSERIAL_MUTEX_UNLOCK();
|
||||
}
|
||||
|
||||
void HardwareSerial::updateBaudRate(unsigned long baud) {
|
||||
uartSetBaudRate(_uart, baud);
|
||||
}
|
||||
|
||||
void HardwareSerial::end() {
|
||||
// default Serial.end() will completely disable HardwareSerial,
|
||||
// including any tasks or debug message channel (log_x()) - but not for IDF log messages!
|
||||
_onReceiveCB = NULL;
|
||||
_onReceiveErrorCB = NULL;
|
||||
if (uartGetDebug() == _uart_nr) {
|
||||
uartSetDebug(0);
|
||||
}
|
||||
_rxFIFOFull = 0;
|
||||
uartEnd(_uart_nr); // fully detach all pins and delete the UART driver
|
||||
_destroyEventTask(); // when IDF uart driver is deleted, _eventTask must finish too
|
||||
_uart = NULL;
|
||||
}
|
||||
|
||||
void HardwareSerial::setDebugOutput(bool en) {
|
||||
if (_uart == 0) {
|
||||
return;
|
||||
}
|
||||
if (en) {
|
||||
uartSetDebug(_uart);
|
||||
} else {
|
||||
if (uartGetDebug() == _uart_nr) {
|
||||
uartSetDebug(NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int HardwareSerial::available(void) {
|
||||
return uartAvailable(_uart);
|
||||
}
|
||||
int HardwareSerial::availableForWrite(void) {
|
||||
return uartAvailableForWrite(_uart);
|
||||
}
|
||||
|
||||
int HardwareSerial::peek(void) {
|
||||
if (available()) {
|
||||
return uartPeek(_uart);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int HardwareSerial::read(void) {
|
||||
uint8_t c = 0;
|
||||
if (uartReadBytes(_uart, &c, 1, 0) == 1) {
|
||||
return c;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// read characters into buffer
|
||||
// terminates if size characters have been read, or no further are pending
|
||||
// returns the number of characters placed in the buffer
|
||||
// the buffer is NOT null terminated.
|
||||
size_t HardwareSerial::read(uint8_t *buffer, size_t size) {
|
||||
return uartReadBytes(_uart, buffer, size, 0);
|
||||
}
|
||||
|
||||
// Overrides Stream::readBytes() to be faster using IDF
|
||||
size_t HardwareSerial::readBytes(uint8_t *buffer, size_t length) {
|
||||
return uartReadBytes(_uart, buffer, length, (uint32_t)getTimeout());
|
||||
}
|
||||
|
||||
void HardwareSerial::flush(void) {
|
||||
uartFlush(_uart);
|
||||
}
|
||||
|
||||
void HardwareSerial::flush(bool txOnly) {
|
||||
uartFlushTxOnly(_uart, txOnly);
|
||||
}
|
||||
|
||||
size_t HardwareSerial::write(uint8_t c) {
|
||||
uartWrite(_uart, c);
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t HardwareSerial::write(const uint8_t *buffer, size_t size) {
|
||||
uartWriteBuf(_uart, buffer, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
uint32_t HardwareSerial::baudRate() {
|
||||
return uartGetBaudRate(_uart);
|
||||
}
|
||||
HardwareSerial::operator bool() const {
|
||||
return uartIsDriverInstalled(_uart);
|
||||
}
|
||||
|
||||
void HardwareSerial::setRxInvert(bool invert) {
|
||||
uartSetRxInvert(_uart, invert);
|
||||
}
|
||||
|
||||
// negative Pin value will keep it unmodified
|
||||
// can be called after or before begin()
|
||||
bool HardwareSerial::setPins(int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin) {
|
||||
// map logical pins to GPIO numbers
|
||||
rxPin = digitalPinToGPIONumber(rxPin);
|
||||
txPin = digitalPinToGPIONumber(txPin);
|
||||
ctsPin = digitalPinToGPIONumber(ctsPin);
|
||||
rtsPin = digitalPinToGPIONumber(rtsPin);
|
||||
|
||||
// uartSetPins() checks if pins are valid and, if necessary, detaches the previous ones
|
||||
return uartSetPins(_uart_nr, rxPin, txPin, ctsPin, rtsPin);
|
||||
}
|
||||
|
||||
// Enables or disables Hardware Flow Control using RTS and/or CTS pins
|
||||
// must use setAllPins() in order to set RTS/CTS pins
|
||||
// SerialHwFlowCtrl = UART_HW_FLOWCTRL_DISABLE, UART_HW_FLOWCTRL_RTS,
|
||||
// UART_HW_FLOWCTRL_CTS, UART_HW_FLOWCTRL_CTS_RTS
|
||||
bool HardwareSerial::setHwFlowCtrlMode(SerialHwFlowCtrl mode, uint8_t threshold) {
|
||||
return uartSetHwFlowCtrlMode(_uart, mode, threshold);
|
||||
}
|
||||
|
||||
// Sets the uart mode in the esp32 uart for use with RS485 modes
|
||||
// HwFlowCtrl must be disabled and RTS pin set
|
||||
// SerialMode = UART_MODE_UART, UART_MODE_RS485_HALF_DUPLEX, UART_MODE_IRDA,
|
||||
// or testing mode: UART_MODE_RS485_COLLISION_DETECT, UART_MODE_RS485_APP_CTRL
|
||||
bool HardwareSerial::setMode(SerialMode mode) {
|
||||
return uartSetMode(_uart, mode);
|
||||
}
|
||||
|
||||
// minimum total RX Buffer size is the UART FIFO space (128 bytes for most SoC) + 1. IDF imposition.
|
||||
size_t HardwareSerial::setRxBufferSize(size_t new_size) {
|
||||
|
||||
if (_uart) {
|
||||
log_e("RX Buffer can't be resized when Serial is already running. Set it before calling begin().");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (new_size <= SOC_UART_FIFO_LEN) {
|
||||
log_w("RX Buffer set to minimum value: %d.", SOC_UART_FIFO_LEN + 1); // ESP32, S2, S3 and C3 means higher than 128
|
||||
new_size = SOC_UART_FIFO_LEN + 1;
|
||||
}
|
||||
|
||||
_rxBufferSize = new_size;
|
||||
return _rxBufferSize;
|
||||
}
|
||||
|
||||
// minimum total TX Buffer size is the UART FIFO space (128 bytes for most SoC).
|
||||
size_t HardwareSerial::setTxBufferSize(size_t new_size) {
|
||||
|
||||
if (_uart) {
|
||||
log_e("TX Buffer can't be resized when Serial is already running. Set it before calling begin().");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (new_size <= SOC_UART_FIFO_LEN) {
|
||||
log_w("TX Buffer set to minimum value: %d.", SOC_UART_FIFO_LEN); // ESP32, S2, S3 and C3 means higher than 128
|
||||
_txBufferSize = 0; // it will use just UART FIFO with SOC_UART_FIFO_LEN bytes (128 for most SoC)
|
||||
return SOC_UART_FIFO_LEN;
|
||||
}
|
||||
// if new_size is higher than SOC_UART_FIFO_LEN, TX Ringbuffer will be active and it will be used to report back "availableToWrite()"
|
||||
_txBufferSize = new_size;
|
||||
return new_size;
|
||||
}
|
||||
|
|
@ -1,368 +0,0 @@
|
|||
/*
|
||||
HardwareSerial.h - Hardware serial library for Wiring
|
||||
Copyright (c) 2006 Nicholas Zambetti. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Modified 28 September 2010 by Mark Sproul
|
||||
Modified 14 August 2012 by Alarus
|
||||
Modified 3 December 2013 by Matthijs Kooijman
|
||||
Modified 18 December 2014 by Ivan Grokhotkov (esp8266 platform support)
|
||||
Modified 31 March 2015 by Markus Sattler (rewrite the code for UART0 + UART1 support in ESP8266)
|
||||
Modified 25 April 2015 by Thomas Flayols (add configuration different from 8N1 in ESP8266)
|
||||
Modified 13 October 2018 by Jeroen Döll (add baudrate detection)
|
||||
Baudrate detection example usage (detection on Serial1):
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
delay(100);
|
||||
Serial.println();
|
||||
|
||||
Serial1.begin(0, SERIAL_8N1, -1, -1, true, 11000UL); // Passing 0 for baudrate to detect it, the last parameter is a timeout in ms
|
||||
|
||||
unsigned long detectedBaudRate = Serial1.baudRate();
|
||||
if(detectedBaudRate) {
|
||||
Serial.printf("Detected baudrate is %lu\n", detectedBaudRate);
|
||||
} else {
|
||||
Serial.println("No baudrate detected, Serial1 will not work!");
|
||||
}
|
||||
}
|
||||
|
||||
Pay attention: the baudrate returned by baudRate() may be rounded, eg 115200 returns 115201
|
||||
*/
|
||||
|
||||
#ifndef HardwareSerial_h
|
||||
#define HardwareSerial_h
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <functional>
|
||||
#include "Stream.h"
|
||||
#include "esp32-hal.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "HWCDC.h"
|
||||
#include "USBCDC.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
|
||||
enum SerialConfig {
|
||||
SERIAL_5N1 = 0x8000010,
|
||||
SERIAL_6N1 = 0x8000014,
|
||||
SERIAL_7N1 = 0x8000018,
|
||||
SERIAL_8N1 = 0x800001c,
|
||||
SERIAL_5N2 = 0x8000030,
|
||||
SERIAL_6N2 = 0x8000034,
|
||||
SERIAL_7N2 = 0x8000038,
|
||||
SERIAL_8N2 = 0x800003c,
|
||||
SERIAL_5E1 = 0x8000012,
|
||||
SERIAL_6E1 = 0x8000016,
|
||||
SERIAL_7E1 = 0x800001a,
|
||||
SERIAL_8E1 = 0x800001e,
|
||||
SERIAL_5E2 = 0x8000032,
|
||||
SERIAL_6E2 = 0x8000036,
|
||||
SERIAL_7E2 = 0x800003a,
|
||||
SERIAL_8E2 = 0x800003e,
|
||||
SERIAL_5O1 = 0x8000013,
|
||||
SERIAL_6O1 = 0x8000017,
|
||||
SERIAL_7O1 = 0x800001b,
|
||||
SERIAL_8O1 = 0x800001f,
|
||||
SERIAL_5O2 = 0x8000033,
|
||||
SERIAL_6O2 = 0x8000037,
|
||||
SERIAL_7O2 = 0x800003b,
|
||||
SERIAL_8O2 = 0x800003f
|
||||
};
|
||||
|
||||
typedef uart_mode_t SerialMode;
|
||||
typedef uart_hw_flowcontrol_t SerialHwFlowCtrl;
|
||||
|
||||
typedef enum {
|
||||
UART_NO_ERROR,
|
||||
UART_BREAK_ERROR,
|
||||
UART_BUFFER_FULL_ERROR,
|
||||
UART_FIFO_OVF_ERROR,
|
||||
UART_FRAME_ERROR,
|
||||
UART_PARITY_ERROR
|
||||
} hardwareSerial_error_t;
|
||||
|
||||
#ifndef ARDUINO_SERIAL_EVENT_TASK_STACK_SIZE
|
||||
#define ARDUINO_SERIAL_EVENT_TASK_STACK_SIZE 2048
|
||||
#endif
|
||||
|
||||
#ifndef ARDUINO_SERIAL_EVENT_TASK_PRIORITY
|
||||
#define ARDUINO_SERIAL_EVENT_TASK_PRIORITY (configMAX_PRIORITIES - 1)
|
||||
#endif
|
||||
|
||||
#ifndef ARDUINO_SERIAL_EVENT_TASK_RUNNING_CORE
|
||||
#define ARDUINO_SERIAL_EVENT_TASK_RUNNING_CORE -1
|
||||
#endif
|
||||
|
||||
// UART0 pins are defined by default by the bootloader.
|
||||
// The definitions for SOC_* should not be changed unless the bootloader pins
|
||||
// have changed and you know what you are doing.
|
||||
|
||||
#ifndef SOC_RX0
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#define SOC_RX0 (gpio_num_t)3
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
#define SOC_RX0 (gpio_num_t)44
|
||||
#elif CONFIG_IDF_TARGET_ESP32C2
|
||||
#define SOC_RX0 (gpio_num_t)19
|
||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||
#define SOC_RX0 (gpio_num_t)20
|
||||
#elif CONFIG_IDF_TARGET_ESP32C6
|
||||
#define SOC_RX0 (gpio_num_t)17
|
||||
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||
#define SOC_RX0 (gpio_num_t)23
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef SOC_TX0
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#define SOC_TX0 (gpio_num_t)1
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
#define SOC_TX0 (gpio_num_t)43
|
||||
#elif CONFIG_IDF_TARGET_ESP32C2
|
||||
#define SOC_TX0 (gpio_num_t)20
|
||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||
#define SOC_TX0 (gpio_num_t)21
|
||||
#elif CONFIG_IDF_TARGET_ESP32C6
|
||||
#define SOC_TX0 (gpio_num_t)16
|
||||
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||
#define SOC_TX0 (gpio_num_t)24
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Default pins for UART1 are arbitrary, and defined here for convenience.
|
||||
|
||||
#if SOC_UART_NUM > 1
|
||||
#ifndef RX1
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#define RX1 (gpio_num_t)26
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#define RX1 (gpio_num_t)4
|
||||
#elif CONFIG_IDF_TARGET_ESP32C2
|
||||
#define RX1 (gpio_num_t)10
|
||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||
#define RX1 (gpio_num_t)18
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
#define RX1 (gpio_num_t)15
|
||||
#elif CONFIG_IDF_TARGET_ESP32C6
|
||||
#define RX1 (gpio_num_t)4
|
||||
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||
#define RX1 (gpio_num_t)0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef TX1
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#define TX1 (gpio_num_t)27
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#define TX1 (gpio_num_t)5
|
||||
#elif CONFIG_IDF_TARGET_ESP32C2
|
||||
#define TX1 (gpio_num_t)18
|
||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||
#define TX1 (gpio_num_t)19
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
#define TX1 (gpio_num_t)16
|
||||
#elif CONFIG_IDF_TARGET_ESP32C6
|
||||
#define TX1 (gpio_num_t)5
|
||||
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||
#define TX1 (gpio_num_t)1
|
||||
#endif
|
||||
#endif
|
||||
#endif /* SOC_UART_NUM > 1 */
|
||||
|
||||
// Default pins for UART2 are arbitrary, and defined here for convenience.
|
||||
|
||||
#if SOC_UART_NUM > 2
|
||||
#ifndef RX2
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#define RX2 (gpio_num_t)4
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
#define RX2 (gpio_num_t)19
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef TX2
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#define TX2 (gpio_num_t)25
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
#define TX2 (gpio_num_t)20
|
||||
#endif
|
||||
#endif
|
||||
#endif /* SOC_UART_NUM > 2 */
|
||||
|
||||
typedef std::function<void(void)> OnReceiveCb;
|
||||
typedef std::function<void(hardwareSerial_error_t)> OnReceiveErrorCb;
|
||||
|
||||
class HardwareSerial : public Stream {
|
||||
public:
|
||||
HardwareSerial(uint8_t uart_nr);
|
||||
~HardwareSerial();
|
||||
|
||||
// setRxTimeout sets the timeout after which onReceive callback will be called (after receiving data, it waits for this time of UART rx inactivity to call the callback fnc)
|
||||
// param symbols_timeout defines a timeout threshold in uart symbol periods. Setting 0 symbol timeout disables the callback call by timeout.
|
||||
// Maximum timeout setting is calculacted automatically by IDF. If set above the maximum, it is ignored and an error is printed on Serial0 (check console).
|
||||
// Examples: Maximum for 11 bits symbol is 92 (SERIAL_8N2, SERIAL_8E1, SERIAL_8O1, etc), Maximum for 10 bits symbol is 101 (SERIAL_8N1).
|
||||
// For example symbols_timeout=1 defines a timeout equal to transmission time of one symbol (~11 bit) on current baudrate.
|
||||
// For a baudrate of 9600, SERIAL_8N1 (10 bit symbol) and symbols_timeout = 3, the timeout would be 3 / (9600 / 10) = 3.125 ms
|
||||
bool setRxTimeout(uint8_t symbols_timeout);
|
||||
|
||||
// setRxFIFOFull(uint8_t fifoBytes) will set the number of bytes that will trigger UART_INTR_RXFIFO_FULL interrupt and fill up RxRingBuffer
|
||||
// This affects some functions such as Serial::available() and Serial.read() because, in a UART flow of receiving data, Serial internal
|
||||
// RxRingBuffer will be filled only after these number of bytes arrive or a RX Timeout happens.
|
||||
// This parameter can be set to 1 in order to receive byte by byte, but it will also consume more CPU time as the ISR will be activates often.
|
||||
bool setRxFIFOFull(uint8_t fifoBytes);
|
||||
|
||||
// onReceive will setup a callback that will be called whenever an UART interruption occurs (UART_INTR_RXFIFO_FULL or UART_INTR_RXFIFO_TOUT)
|
||||
// UART_INTR_RXFIFO_FULL interrupt triggers at UART_FULL_THRESH_DEFAULT bytes received (defined as 120 bytes by default in IDF)
|
||||
// UART_INTR_RXFIFO_TOUT interrupt triggers at UART_TOUT_THRESH_DEFAULT symbols passed without any reception (defined as 10 symbos by default in IDF)
|
||||
// onlyOnTimeout parameter will define how onReceive will behave:
|
||||
// Default: true -- The callback will only be called when RX Timeout happens.
|
||||
// Whole stream of bytes will be ready for being read on the callback function at once.
|
||||
// This option may lead to Rx Overflow depending on the Rx Buffer Size and number of bytes received in the streaming
|
||||
// false -- The callback will be called when FIFO reaches 120 bytes and also on RX Timeout.
|
||||
// The stream of incommig bytes will be "split" into blocks of 120 bytes on each callback.
|
||||
// This option avoid any sort of Rx Overflow, but leaves the UART packet reassembling work to the Application.
|
||||
void onReceive(OnReceiveCb function, bool onlyOnTimeout = false);
|
||||
|
||||
// onReceive will be called on error events (see hardwareSerial_error_t)
|
||||
void onReceiveError(OnReceiveErrorCb function);
|
||||
|
||||
// eventQueueReset clears all events in the queue (the events that trigger onReceive and onReceiveError) - maybe useful in some use cases
|
||||
void eventQueueReset();
|
||||
|
||||
// When pins are changed, it will detach the previous ones
|
||||
// if pin is negative, it won't be set/changed and will be kept as is
|
||||
// timeout_ms is used in baudrate detection (ESP32, ESP32S2 only)
|
||||
// invert will invert RX/TX polarity
|
||||
// rxfifo_full_thrhd if the UART Flow Control Threshold in the UART FIFO (max 127)
|
||||
void begin(
|
||||
unsigned long baud, uint32_t config = SERIAL_8N1, int8_t rxPin = -1, int8_t txPin = -1, bool invert = false, unsigned long timeout_ms = 20000UL,
|
||||
uint8_t rxfifo_full_thrhd = 112
|
||||
);
|
||||
void end(void);
|
||||
void updateBaudRate(unsigned long baud);
|
||||
int available(void);
|
||||
int availableForWrite(void);
|
||||
int peek(void);
|
||||
int read(void);
|
||||
size_t read(uint8_t *buffer, size_t size);
|
||||
inline size_t read(char *buffer, size_t size) {
|
||||
return read((uint8_t *)buffer, size);
|
||||
}
|
||||
// Overrides Stream::readBytes() to be faster using IDF
|
||||
size_t readBytes(uint8_t *buffer, size_t length);
|
||||
size_t readBytes(char *buffer, size_t length) {
|
||||
return readBytes((uint8_t *)buffer, length);
|
||||
}
|
||||
void flush(void);
|
||||
void flush(bool txOnly);
|
||||
size_t write(uint8_t);
|
||||
size_t write(const uint8_t *buffer, size_t size);
|
||||
inline size_t write(const char *buffer, size_t size) {
|
||||
return write((uint8_t *)buffer, size);
|
||||
}
|
||||
inline size_t write(const char *s) {
|
||||
return write((uint8_t *)s, strlen(s));
|
||||
}
|
||||
inline size_t write(unsigned long n) {
|
||||
return write((uint8_t)n);
|
||||
}
|
||||
inline size_t write(long n) {
|
||||
return write((uint8_t)n);
|
||||
}
|
||||
inline size_t write(unsigned int n) {
|
||||
return write((uint8_t)n);
|
||||
}
|
||||
inline size_t write(int n) {
|
||||
return write((uint8_t)n);
|
||||
}
|
||||
uint32_t baudRate();
|
||||
operator bool() const;
|
||||
|
||||
void setDebugOutput(bool);
|
||||
|
||||
void setRxInvert(bool);
|
||||
|
||||
// Negative Pin Number will keep it unmodified, thus this function can set individual pins
|
||||
// setPins() can be called after or before begin()
|
||||
// When pins are changed, it will detach the previous ones
|
||||
bool setPins(int8_t rxPin, int8_t txPin, int8_t ctsPin = -1, int8_t rtsPin = -1);
|
||||
// Enables or disables Hardware Flow Control using RTS and/or CTS pins (must use setAllPins() before)
|
||||
// UART_HW_FLOWCTRL_DISABLE = 0x0 disable hardware flow control
|
||||
// UART_HW_FLOWCTRL_RTS = 0x1 enable RX hardware flow control (rts)
|
||||
// UART_HW_FLOWCTRL_CTS = 0x2 enable TX hardware flow control (cts)
|
||||
// UART_HW_FLOWCTRL_CTS_RTS = 0x3 enable hardware flow control
|
||||
bool setHwFlowCtrlMode(SerialHwFlowCtrl mode = UART_HW_FLOWCTRL_CTS_RTS, uint8_t threshold = 64); // 64 is half FIFO Length
|
||||
// Used to set RS485 modes such as UART_MODE_RS485_HALF_DUPLEX for Auto RTS function on ESP32
|
||||
// UART_MODE_UART = 0x00 mode: regular UART mode
|
||||
// UART_MODE_RS485_HALF_DUPLEX = 0x01 mode: half duplex RS485 UART mode control by RTS pin
|
||||
// UART_MODE_IRDA = 0x02 mode: IRDA UART mode
|
||||
// UART_MODE_RS485_COLLISION_DETECT = 0x03 mode: RS485 collision detection UART mode (used for test purposes)
|
||||
// UART_MODE_RS485_APP_CTRL = 0x04 mode: application control RS485 UART mode (used for test purposes)
|
||||
bool setMode(SerialMode mode);
|
||||
size_t setRxBufferSize(size_t new_size);
|
||||
size_t setTxBufferSize(size_t new_size);
|
||||
|
||||
protected:
|
||||
uint8_t _uart_nr;
|
||||
uart_t *_uart;
|
||||
size_t _rxBufferSize;
|
||||
size_t _txBufferSize;
|
||||
OnReceiveCb _onReceiveCB;
|
||||
OnReceiveErrorCb _onReceiveErrorCB;
|
||||
// _onReceive and _rxTimeout have be consistent when timeout is disabled
|
||||
bool _onReceiveTimeout;
|
||||
uint8_t _rxTimeout, _rxFIFOFull;
|
||||
TaskHandle_t _eventTask;
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
SemaphoreHandle_t _lock;
|
||||
#endif
|
||||
|
||||
void _createEventTask(void *args);
|
||||
void _destroyEventTask(void);
|
||||
static void _uartEventTask(void *args);
|
||||
};
|
||||
|
||||
extern void serialEventRun(void) __attribute__((weak));
|
||||
|
||||
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL)
|
||||
#ifndef ARDUINO_USB_CDC_ON_BOOT
|
||||
#define ARDUINO_USB_CDC_ON_BOOT 0
|
||||
#endif
|
||||
#if ARDUINO_USB_CDC_ON_BOOT //Serial used from Native_USB_CDC | HW_CDC_JTAG
|
||||
#if ARDUINO_USB_MODE // Hardware CDC mode
|
||||
// Arduino Serial is the HW JTAG CDC device
|
||||
#define Serial HWCDCSerial
|
||||
#else // !ARDUINO_USB_MODE -- Native USB Mode
|
||||
// Arduino Serial is the Native USB CDC device
|
||||
#define Serial USBSerial
|
||||
#endif // ARDUINO_USB_MODE
|
||||
#else // !ARDUINO_USB_CDC_ON_BOOT -- Serial is used from UART0
|
||||
// if not using CDC on Boot, Arduino Serial is the UART0 device
|
||||
#define Serial Serial0
|
||||
#endif // ARDUINO_USB_CDC_ON_BOOT
|
||||
// There is always Seria0 for UART0
|
||||
extern HardwareSerial Serial0;
|
||||
#if SOC_UART_NUM > 1
|
||||
extern HardwareSerial Serial1;
|
||||
#endif
|
||||
#if SOC_UART_NUM > 2
|
||||
extern HardwareSerial Serial2;
|
||||
#endif
|
||||
#endif //!defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL)
|
||||
|
||||
#endif // HardwareSerial_h
|
||||
|
|
@ -1,94 +0,0 @@
|
|||
/*
|
||||
IPAddress.h - Base class that provides IPAddress
|
||||
Copyright (c) 2011 Adrian McEwen. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef IPAddress_h
|
||||
#define IPAddress_h
|
||||
|
||||
#include <stdint.h>
|
||||
#include "WString.h"
|
||||
#include "Printable.h"
|
||||
|
||||
// A class to make it easier to handle and pass around IP addresses
|
||||
|
||||
class IPAddress: public Printable
|
||||
{
|
||||
private:
|
||||
union {
|
||||
uint8_t bytes[4]; // IPv4 address
|
||||
uint32_t dword;
|
||||
} _address;
|
||||
|
||||
// Access the raw byte array containing the address. Because this returns a pointer
|
||||
// to the internal structure rather than a copy of the address this function should only
|
||||
// be used when you know that the usage of the returned uint8_t* will be transient and not
|
||||
// stored.
|
||||
uint8_t* raw_address()
|
||||
{
|
||||
return _address.bytes;
|
||||
}
|
||||
|
||||
public:
|
||||
// Constructors
|
||||
IPAddress();
|
||||
IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet);
|
||||
IPAddress(uint32_t address);
|
||||
IPAddress(const uint8_t *address);
|
||||
virtual ~IPAddress() {}
|
||||
|
||||
bool fromString(const char *address);
|
||||
bool fromString(const String &address) { return fromString(address.c_str()); }
|
||||
|
||||
// Overloaded cast operator to allow IPAddress objects to be used where a pointer
|
||||
// to a four-byte uint8_t array is expected
|
||||
operator uint32_t() const
|
||||
{
|
||||
return _address.dword;
|
||||
}
|
||||
bool operator==(const IPAddress& addr) const
|
||||
{
|
||||
return _address.dword == addr._address.dword;
|
||||
}
|
||||
bool operator==(const uint8_t* addr) const;
|
||||
|
||||
// Overloaded index operator to allow getting and setting individual octets of the address
|
||||
uint8_t operator[](int index) const
|
||||
{
|
||||
return _address.bytes[index];
|
||||
}
|
||||
uint8_t& operator[](int index)
|
||||
{
|
||||
return _address.bytes[index];
|
||||
}
|
||||
|
||||
// Overloaded copy operators to allow initialisation of IPAddress objects from other types
|
||||
IPAddress& operator=(const uint8_t *address);
|
||||
IPAddress& operator=(uint32_t address);
|
||||
|
||||
virtual size_t printTo(Print& p) const;
|
||||
String toString() const;
|
||||
|
||||
friend class EthernetClass;
|
||||
friend class UDP;
|
||||
friend class Client;
|
||||
friend class Server;
|
||||
friend class DhcpClass;
|
||||
friend class DNSClient;
|
||||
};
|
||||
|
||||
#endif
|
||||
201
arduino/LICENSE
201
arduino/LICENSE
|
|
@ -1,201 +0,0 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2017 Neil Kolban
|
||||
|
||||
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.
|
||||
|
|
@ -1,374 +0,0 @@
|
|||
/*
|
||||
Print.cpp - Base class that provides print() and println()
|
||||
Copyright (c) 2008 David A. Mellis. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Modified 23 November 2006 by David A. Mellis
|
||||
Modified December 2014 by Ivan Grokhotkov
|
||||
Modified May 2015 by Michael C. Miller - ESP31B progmem support
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "Arduino.h"
|
||||
|
||||
#include "Print.h"
|
||||
extern "C" {
|
||||
#include "time.h"
|
||||
}
|
||||
|
||||
// Public Methods //////////////////////////////////////////////////////////////
|
||||
|
||||
/* default implementation: may be overridden */
|
||||
size_t Print::write(const uint8_t *buffer, size_t size)
|
||||
{
|
||||
size_t n = 0;
|
||||
while(size--) {
|
||||
n += write(*buffer++);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::printf(const char *format, ...)
|
||||
{
|
||||
char loc_buf[64];
|
||||
char * temp = loc_buf;
|
||||
va_list arg;
|
||||
va_list copy;
|
||||
va_start(arg, format);
|
||||
va_copy(copy, arg);
|
||||
int len = vsnprintf(temp, sizeof(loc_buf), format, copy);
|
||||
va_end(copy);
|
||||
if(len < 0) {
|
||||
va_end(arg);
|
||||
return 0;
|
||||
};
|
||||
if(len >= sizeof(loc_buf)){
|
||||
temp = (char*) malloc(len+1);
|
||||
if(temp == NULL) {
|
||||
va_end(arg);
|
||||
return 0;
|
||||
}
|
||||
len = vsnprintf(temp, len+1, format, arg);
|
||||
}
|
||||
va_end(arg);
|
||||
len = write((uint8_t*)temp, len);
|
||||
if(temp != loc_buf){
|
||||
free(temp);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
size_t Print::print(const __FlashStringHelper *ifsh)
|
||||
{
|
||||
return print(reinterpret_cast<const char *>(ifsh));
|
||||
}
|
||||
|
||||
size_t Print::print(const String &s)
|
||||
{
|
||||
return write(s.c_str(), s.length());
|
||||
}
|
||||
|
||||
size_t Print::print(const char str[])
|
||||
{
|
||||
return write(str);
|
||||
}
|
||||
|
||||
size_t Print::print(char c)
|
||||
{
|
||||
return write(c);
|
||||
}
|
||||
|
||||
size_t Print::print(unsigned char b, int base)
|
||||
{
|
||||
return print((unsigned long) b, base);
|
||||
}
|
||||
|
||||
size_t Print::print(int n, int base)
|
||||
{
|
||||
return print((long) n, base);
|
||||
}
|
||||
|
||||
size_t Print::print(unsigned int n, int base)
|
||||
{
|
||||
return print((unsigned long) n, base);
|
||||
}
|
||||
|
||||
size_t Print::print(long n, int base)
|
||||
{
|
||||
int t = 0;
|
||||
if (base == 10 && n < 0) {
|
||||
t = print('-');
|
||||
n = -n;
|
||||
}
|
||||
return printNumber(static_cast<unsigned long>(n), base) + t;
|
||||
}
|
||||
|
||||
size_t Print::print(unsigned long n, int base)
|
||||
{
|
||||
if(base == 0) {
|
||||
return write(n);
|
||||
} else {
|
||||
return printNumber(n, base);
|
||||
}
|
||||
}
|
||||
|
||||
size_t Print::print(long long n, int base)
|
||||
{
|
||||
int t = 0;
|
||||
if (base == 10 && n < 0) {
|
||||
t = print('-');
|
||||
n = -n;
|
||||
}
|
||||
return printNumber(static_cast<unsigned long long>(n), base) + t;
|
||||
}
|
||||
|
||||
size_t Print::print(unsigned long long n, int base)
|
||||
{
|
||||
if (base == 0) {
|
||||
return write(n);
|
||||
} else {
|
||||
return printNumber(n, base);
|
||||
}
|
||||
}
|
||||
|
||||
size_t Print::print(double n, int digits)
|
||||
{
|
||||
return printFloat(n, digits);
|
||||
}
|
||||
|
||||
size_t Print::println(const __FlashStringHelper *ifsh)
|
||||
{
|
||||
size_t n = print(ifsh);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::print(const Printable& x)
|
||||
{
|
||||
return x.printTo(*this);
|
||||
}
|
||||
|
||||
size_t Print::print(struct tm * timeinfo, const char * format)
|
||||
{
|
||||
const char * f = format;
|
||||
if(!f){
|
||||
f = "%c";
|
||||
}
|
||||
char buf[64];
|
||||
size_t written = strftime(buf, 64, f, timeinfo);
|
||||
if(written == 0){
|
||||
return written;
|
||||
}
|
||||
return print(buf);
|
||||
}
|
||||
|
||||
size_t Print::println(void)
|
||||
{
|
||||
return print("\r\n");
|
||||
}
|
||||
|
||||
size_t Print::println(const String &s)
|
||||
{
|
||||
size_t n = print(s);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(const char c[])
|
||||
{
|
||||
size_t n = print(c);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(char c)
|
||||
{
|
||||
size_t n = print(c);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(unsigned char b, int base)
|
||||
{
|
||||
size_t n = print(b, base);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(int num, int base)
|
||||
{
|
||||
size_t n = print(num, base);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(unsigned int num, int base)
|
||||
{
|
||||
size_t n = print(num, base);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(long num, int base)
|
||||
{
|
||||
size_t n = print(num, base);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(unsigned long num, int base)
|
||||
{
|
||||
size_t n = print(num, base);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(long long num, int base)
|
||||
{
|
||||
size_t n = print(num, base);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(unsigned long long num, int base)
|
||||
{
|
||||
size_t n = print(num, base);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(double num, int digits)
|
||||
{
|
||||
size_t n = print(num, digits);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(const Printable& x)
|
||||
{
|
||||
size_t n = print(x);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(struct tm * timeinfo, const char * format)
|
||||
{
|
||||
size_t n = print(timeinfo, format);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
// Private Methods /////////////////////////////////////////////////////////////
|
||||
|
||||
size_t Print::printNumber(unsigned long n, uint8_t base)
|
||||
{
|
||||
char buf[8 * sizeof(n) + 1]; // Assumes 8-bit chars plus zero byte.
|
||||
char *str = &buf[sizeof(buf) - 1];
|
||||
|
||||
*str = '\0';
|
||||
|
||||
// prevent crash if called with base == 1
|
||||
if(base < 2) {
|
||||
base = 10;
|
||||
}
|
||||
|
||||
do {
|
||||
char c = n % base;
|
||||
n /= base;
|
||||
|
||||
*--str = c < 10 ? c + '0' : c + 'A' - 10;
|
||||
} while (n);
|
||||
|
||||
return write(str);
|
||||
}
|
||||
|
||||
size_t Print::printNumber(unsigned long long n, uint8_t base)
|
||||
{
|
||||
char buf[8 * sizeof(n) + 1]; // Assumes 8-bit chars plus zero byte.
|
||||
char* str = &buf[sizeof(buf) - 1];
|
||||
|
||||
*str = '\0';
|
||||
|
||||
// prevent crash if called with base == 1
|
||||
if (base < 2) {
|
||||
base = 10;
|
||||
}
|
||||
|
||||
do {
|
||||
auto m = n;
|
||||
n /= base;
|
||||
char c = m - base * n;
|
||||
|
||||
*--str = c < 10 ? c + '0' : c + 'A' - 10;
|
||||
} while (n);
|
||||
|
||||
return write(str);
|
||||
}
|
||||
|
||||
size_t Print::printFloat(double number, uint8_t digits)
|
||||
{
|
||||
size_t n = 0;
|
||||
|
||||
if(isnan(number)) {
|
||||
return print("nan");
|
||||
}
|
||||
if(isinf(number)) {
|
||||
return print("inf");
|
||||
}
|
||||
if(number > 4294967040.0) {
|
||||
return print("ovf"); // constant determined empirically
|
||||
}
|
||||
if(number < -4294967040.0) {
|
||||
return print("ovf"); // constant determined empirically
|
||||
}
|
||||
|
||||
// Handle negative numbers
|
||||
if(number < 0.0) {
|
||||
n += print('-');
|
||||
number = -number;
|
||||
}
|
||||
|
||||
// Round correctly so that print(1.999, 2) prints as "2.00"
|
||||
double rounding = 0.5;
|
||||
for(uint8_t i = 0; i < digits; ++i) {
|
||||
rounding /= 10.0;
|
||||
}
|
||||
|
||||
number += rounding;
|
||||
|
||||
// Extract the integer part of the number and print it
|
||||
unsigned long int_part = (unsigned long) number;
|
||||
double remainder = number - (double) int_part;
|
||||
n += print(int_part);
|
||||
|
||||
// Print the decimal point, but only if there are digits beyond
|
||||
if(digits > 0) {
|
||||
n += print(".");
|
||||
}
|
||||
|
||||
// Extract digits from the remainder one at a time
|
||||
while(digits-- > 0) {
|
||||
remainder *= 10.0;
|
||||
int toPrint = int(remainder);
|
||||
n += print(toPrint);
|
||||
remainder -= toPrint;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
113
arduino/Print.h
113
arduino/Print.h
|
|
@ -1,113 +0,0 @@
|
|||
/*
|
||||
Print.h - Base class that provides print() and println()
|
||||
Copyright (c) 2008 David A. Mellis. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef Print_h
|
||||
#define Print_h
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "WString.h"
|
||||
#include "Printable.h"
|
||||
|
||||
#define DEC 10
|
||||
#define HEX 16
|
||||
#define OCT 8
|
||||
#define BIN 2
|
||||
|
||||
class Print
|
||||
{
|
||||
private:
|
||||
int write_error;
|
||||
size_t printNumber(unsigned long, uint8_t);
|
||||
size_t printNumber(unsigned long long, uint8_t);
|
||||
size_t printFloat(double, uint8_t);
|
||||
protected:
|
||||
void setWriteError(int err = 1)
|
||||
{
|
||||
write_error = err;
|
||||
}
|
||||
public:
|
||||
Print() :
|
||||
write_error(0)
|
||||
{
|
||||
}
|
||||
virtual ~Print() {}
|
||||
int getWriteError()
|
||||
{
|
||||
return write_error;
|
||||
}
|
||||
void clearWriteError()
|
||||
{
|
||||
setWriteError(0);
|
||||
}
|
||||
|
||||
virtual size_t write(uint8_t) = 0;
|
||||
size_t write(const char *str)
|
||||
{
|
||||
if(str == NULL) {
|
||||
return 0;
|
||||
}
|
||||
return write((const uint8_t *) str, strlen(str));
|
||||
}
|
||||
virtual size_t write(const uint8_t *buffer, size_t size);
|
||||
size_t write(const char *buffer, size_t size)
|
||||
{
|
||||
return write((const uint8_t *) buffer, size);
|
||||
}
|
||||
|
||||
size_t printf(const char * format, ...) __attribute__ ((format (printf, 2, 3)));
|
||||
|
||||
// add availableForWrite to make compatible with Arduino Print.h
|
||||
// default to zero, meaning "a single write may block"
|
||||
// should be overriden by subclasses with buffering
|
||||
virtual int availableForWrite() { return 0; }
|
||||
size_t print(const __FlashStringHelper *);
|
||||
size_t print(const String &);
|
||||
size_t print(const char[]);
|
||||
size_t print(char);
|
||||
size_t print(unsigned char, int = DEC);
|
||||
size_t print(int, int = DEC);
|
||||
size_t print(unsigned int, int = DEC);
|
||||
size_t print(long, int = DEC);
|
||||
size_t print(unsigned long, int = DEC);
|
||||
size_t print(long long, int = DEC);
|
||||
size_t print(unsigned long long, int = DEC);
|
||||
size_t print(double, int = 2);
|
||||
size_t print(const Printable&);
|
||||
size_t print(struct tm * timeinfo, const char * format = NULL);
|
||||
|
||||
size_t println(const __FlashStringHelper *);
|
||||
size_t println(const String &s);
|
||||
size_t println(const char[]);
|
||||
size_t println(char);
|
||||
size_t println(unsigned char, int = DEC);
|
||||
size_t println(int, int = DEC);
|
||||
size_t println(unsigned int, int = DEC);
|
||||
size_t println(long, int = DEC);
|
||||
size_t println(unsigned long, int = DEC);
|
||||
size_t println(long long, int = DEC);
|
||||
size_t println(unsigned long long, int = DEC);
|
||||
size_t println(double, int = 2);
|
||||
size_t println(const Printable&);
|
||||
size_t println(struct tm * timeinfo, const char * format = NULL);
|
||||
size_t println(void);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
/*
|
||||
Printable.h - Interface class that allows printing of complex types
|
||||
Copyright (c) 2011 Adrian McEwen. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef Printable_h
|
||||
#define Printable_h
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
class Print;
|
||||
|
||||
/** The Printable class provides a way for new classes to allow themselves to be printed.
|
||||
By deriving from Printable and implementing the printTo method, it will then be possible
|
||||
for users to print out instances of this class by passing them into the usual
|
||||
Print::print and Print::println methods.
|
||||
*/
|
||||
|
||||
class Printable
|
||||
{
|
||||
public:
|
||||
virtual ~Printable() {}
|
||||
virtual size_t printTo(Print& p) const = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
MOst of the files here are taken from Arduino version 15 and covered by
|
||||
the file, LICENCE, with these exceptions:
|
||||
|
||||
RPLidar.cpp, RPLidar.h rplidar_cmd.h rplidar_protocol.h rptypes.h:
|
||||
Copyright (c) 2014, RoboPeak - copyright notices are in individual files
|
||||
|
||||
analogWrite.cpp analogWrite.h - Copyright (c) 2019 ERROPiX, MIT license
|
||||
|
||||
|
|
@ -1,336 +0,0 @@
|
|||
/*
|
||||
* RoboPeak RPLIDAR Driver for Arduino
|
||||
* RoboPeak.com
|
||||
*
|
||||
* Copyright (c) 2014, RoboPeak
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
||||
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "RPLidar.h"
|
||||
|
||||
RPLidar::RPLidar()
|
||||
: _bined_serialdev(NULL)
|
||||
{
|
||||
_currentMeasurement.distance = 0;
|
||||
_currentMeasurement.angle = 0;
|
||||
_currentMeasurement.quality = 0;
|
||||
_currentMeasurement.startBit = 0;
|
||||
}
|
||||
|
||||
|
||||
RPLidar::~RPLidar()
|
||||
{
|
||||
end();
|
||||
}
|
||||
|
||||
// open the given serial interface and try to connect to the RPLIDAR
|
||||
bool RPLidar::begin(HardwareSerial &serialobj)
|
||||
{
|
||||
if (isOpen()) {
|
||||
end();
|
||||
}
|
||||
_bined_serialdev = &serialobj;
|
||||
_bined_serialdev->end();
|
||||
_bined_serialdev->begin(RPLIDAR_SERIAL_BAUDRATE);
|
||||
return (1);
|
||||
}
|
||||
|
||||
// close the currently opened serial interface
|
||||
void RPLidar::end()
|
||||
{
|
||||
if (isOpen()) {
|
||||
_bined_serialdev->end();
|
||||
_bined_serialdev = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// check whether the serial interface is opened
|
||||
bool RPLidar::isOpen()
|
||||
{
|
||||
return _bined_serialdev?true:false;
|
||||
}
|
||||
|
||||
// ask the RPLIDAR for its health info
|
||||
u_result RPLidar::getHealth(rplidar_response_device_health_t & healthinfo, _u32 timeout)
|
||||
{
|
||||
_u32 currentTs = millis();
|
||||
_u32 remainingtime;
|
||||
|
||||
_u8 *infobuf = (_u8 *)&healthinfo;
|
||||
_u8 recvPos = 0;
|
||||
|
||||
rplidar_ans_header_t response_header;
|
||||
u_result ans;
|
||||
|
||||
|
||||
if (!isOpen()) return RESULT_OPERATION_FAIL;
|
||||
|
||||
{
|
||||
if (IS_FAIL(ans = _sendCommand(RPLIDAR_CMD_GET_DEVICE_HEALTH, NULL, 0))) {
|
||||
return ans;
|
||||
}
|
||||
|
||||
if (IS_FAIL(ans = _waitResponseHeader(&response_header, timeout))) {
|
||||
return ans;
|
||||
}
|
||||
|
||||
// verify whether we got a correct header
|
||||
if (response_header.type != RPLIDAR_ANS_TYPE_DEVHEALTH) {
|
||||
return RESULT_INVALID_DATA;
|
||||
}
|
||||
|
||||
if ((response_header.size) < sizeof(rplidar_response_device_health_t)) {
|
||||
return RESULT_INVALID_DATA;
|
||||
}
|
||||
|
||||
while ((remainingtime=millis() - currentTs) <= timeout) {
|
||||
int currentbyte = _bined_serialdev->read();
|
||||
if (currentbyte < 0) continue;
|
||||
|
||||
infobuf[recvPos++] = currentbyte;
|
||||
|
||||
if (recvPos == sizeof(rplidar_response_device_health_t)) {
|
||||
return RESULT_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
return RESULT_OPERATION_TIMEOUT;
|
||||
}
|
||||
|
||||
// ask the RPLIDAR for its device info like the serial number
|
||||
u_result RPLidar::getDeviceInfo(rplidar_response_device_info_t & info, _u32 timeout )
|
||||
{
|
||||
_u8 recvPos = 0;
|
||||
_u32 currentTs = millis();
|
||||
_u32 remainingtime;
|
||||
_u8 *infobuf = (_u8*)&info;
|
||||
rplidar_ans_header_t response_header;
|
||||
u_result ans;
|
||||
|
||||
if (!isOpen()) return RESULT_OPERATION_FAIL;
|
||||
|
||||
{
|
||||
if (IS_FAIL(ans = _sendCommand(RPLIDAR_CMD_GET_DEVICE_INFO,NULL,0))) {
|
||||
return ans;
|
||||
}
|
||||
|
||||
if (IS_FAIL(ans = _waitResponseHeader(&response_header, timeout))) {
|
||||
return ans;
|
||||
}
|
||||
|
||||
// verify whether we got a correct header
|
||||
if (response_header.type != RPLIDAR_ANS_TYPE_DEVINFO) {
|
||||
return RESULT_INVALID_DATA;
|
||||
}
|
||||
|
||||
if (response_header.size < sizeof(rplidar_response_device_info_t)) {
|
||||
return RESULT_INVALID_DATA;
|
||||
}
|
||||
|
||||
while ((remainingtime=millis() - currentTs) <= timeout) {
|
||||
int currentbyte = _bined_serialdev->read();
|
||||
if (currentbyte<0) continue;
|
||||
infobuf[recvPos++] = currentbyte;
|
||||
|
||||
if (recvPos == sizeof(rplidar_response_device_info_t)) {
|
||||
return RESULT_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return RESULT_OPERATION_TIMEOUT;
|
||||
}
|
||||
|
||||
// stop the measurement operation
|
||||
u_result RPLidar::stop()
|
||||
{
|
||||
if (!isOpen()) return RESULT_OPERATION_FAIL;
|
||||
u_result ans = _sendCommand(RPLIDAR_CMD_STOP,NULL,0);
|
||||
return ans;
|
||||
}
|
||||
|
||||
// start the measurement operation
|
||||
u_result RPLidar::startScan(bool force, _u32 timeout)
|
||||
{
|
||||
u_result ans;
|
||||
|
||||
if (!isOpen()) return RESULT_OPERATION_FAIL;
|
||||
|
||||
stop(); //force the previous operation to stop
|
||||
|
||||
{
|
||||
ans = _sendCommand(force?RPLIDAR_CMD_FORCE_SCAN:RPLIDAR_CMD_SCAN, NULL, 0);
|
||||
if (IS_FAIL(ans)) return ans;
|
||||
|
||||
// waiting for confirmation
|
||||
rplidar_ans_header_t response_header;
|
||||
if (IS_FAIL(ans = _waitResponseHeader(&response_header, timeout))) {
|
||||
return ans;
|
||||
}
|
||||
|
||||
// verify whether we got a correct header
|
||||
if (response_header.type != RPLIDAR_ANS_TYPE_MEASUREMENT) {
|
||||
return RESULT_INVALID_DATA;
|
||||
}
|
||||
|
||||
if (response_header.size < sizeof(rplidar_response_measurement_node_t)) {
|
||||
return RESULT_INVALID_DATA;
|
||||
}
|
||||
}
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
// wait for one sample point to arrive
|
||||
u_result RPLidar::waitPoint(_u32 timeout)
|
||||
{
|
||||
_u32 currentTs = millis();
|
||||
_u32 remainingtime;
|
||||
rplidar_response_measurement_node_t node;
|
||||
_u8 *nodebuf = (_u8*)&node;
|
||||
|
||||
_u8 recvPos = 0;
|
||||
|
||||
while ((remainingtime=millis() - currentTs) <= timeout) {
|
||||
int currentbyte = _bined_serialdev->read();
|
||||
if (currentbyte<0) continue;
|
||||
|
||||
switch (recvPos) {
|
||||
case 0: // expect the sync bit and its reverse in this byte {
|
||||
{
|
||||
_u8 tmp = (currentbyte>>1);
|
||||
if ( (tmp ^ currentbyte) & 0x1 ) {
|
||||
// pass
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
case 1: // expect the highest bit to be 1
|
||||
{
|
||||
if (currentbyte & RPLIDAR_RESP_MEASUREMENT_CHECKBIT) {
|
||||
// pass
|
||||
} else {
|
||||
recvPos = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
nodebuf[recvPos++] = currentbyte;
|
||||
|
||||
if (recvPos == sizeof(rplidar_response_measurement_node_t)) {
|
||||
// store the data ...
|
||||
_currentMeasurement.distance = node.distance_q2/4.0f;
|
||||
_currentMeasurement.angle = (node.angle_q6_checkbit >> RPLIDAR_RESP_MEASUREMENT_ANGLE_SHIFT)/64.0f;
|
||||
_currentMeasurement.quality = (node.sync_quality>>RPLIDAR_RESP_MEASUREMENT_QUALITY_SHIFT);
|
||||
_currentMeasurement.startBit = (node.sync_quality & RPLIDAR_RESP_MEASUREMENT_SYNCBIT);
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return RESULT_OPERATION_TIMEOUT;
|
||||
}
|
||||
|
||||
|
||||
|
||||
u_result RPLidar::_sendCommand(_u8 cmd, const void * payload, size_t payloadsize)
|
||||
{
|
||||
|
||||
rplidar_cmd_packet_t pkt_header;
|
||||
rplidar_cmd_packet_t * header = &pkt_header;
|
||||
_u8 checksum = 0;
|
||||
|
||||
if (payloadsize && payload) {
|
||||
cmd |= RPLIDAR_CMDFLAG_HAS_PAYLOAD;
|
||||
}
|
||||
|
||||
header->syncByte = RPLIDAR_CMD_SYNC_BYTE;
|
||||
header->cmd_flag = cmd;
|
||||
|
||||
// send header first
|
||||
_bined_serialdev->write( (uint8_t *)header, 2);
|
||||
|
||||
if (cmd & RPLIDAR_CMDFLAG_HAS_PAYLOAD) {
|
||||
checksum ^= RPLIDAR_CMD_SYNC_BYTE;
|
||||
checksum ^= cmd;
|
||||
checksum ^= (payloadsize & 0xFF);
|
||||
|
||||
// calc checksum
|
||||
for (size_t pos = 0; pos < payloadsize; ++pos) {
|
||||
checksum ^= ((_u8 *)payload)[pos];
|
||||
}
|
||||
|
||||
// send size
|
||||
_u8 sizebyte = payloadsize;
|
||||
_bined_serialdev->write((uint8_t *)&sizebyte, 1);
|
||||
|
||||
// send payload
|
||||
_bined_serialdev->write((uint8_t *)&payload, sizebyte);
|
||||
|
||||
// send checksum
|
||||
_bined_serialdev->write((uint8_t *)&checksum, 1);
|
||||
|
||||
}
|
||||
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
u_result RPLidar::_waitResponseHeader(rplidar_ans_header_t * header, _u32 timeout)
|
||||
{
|
||||
_u8 recvPos = 0;
|
||||
_u32 currentTs = millis();
|
||||
_u32 remainingtime;
|
||||
_u8 *headerbuf = (_u8*)header;
|
||||
while ((remainingtime=millis() - currentTs) <= timeout) {
|
||||
|
||||
int currentbyte = _bined_serialdev->read();
|
||||
if (currentbyte<0) continue;
|
||||
switch (recvPos) {
|
||||
case 0:
|
||||
if (currentbyte != RPLIDAR_ANS_SYNC_BYTE1) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (currentbyte != RPLIDAR_ANS_SYNC_BYTE2) {
|
||||
recvPos = 0;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
headerbuf[recvPos++] = currentbyte;
|
||||
|
||||
if (recvPos == sizeof(rplidar_ans_header_t)) {
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
return RESULT_OPERATION_TIMEOUT;
|
||||
}
|
||||
|
||||
|
|
@ -1,93 +0,0 @@
|
|||
/*
|
||||
* RoboPeak RPLIDAR Driver for Arduino
|
||||
* RoboPeak.com
|
||||
*
|
||||
* Copyright (c) 2014, RoboPeak
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
||||
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "rptypes.h"
|
||||
#include "rplidar_cmd.h"
|
||||
|
||||
struct RPLidarMeasurement
|
||||
{
|
||||
float distance;
|
||||
float angle;
|
||||
uint8_t quality;
|
||||
bool startBit;
|
||||
};
|
||||
|
||||
class RPLidar
|
||||
{
|
||||
public:
|
||||
enum {
|
||||
RPLIDAR_SERIAL_BAUDRATE = 115200,
|
||||
RPLIDAR_DEFAULT_TIMEOUT = 500,
|
||||
};
|
||||
|
||||
RPLidar();
|
||||
~RPLidar();
|
||||
|
||||
// open the given serial interface and try to connect to the RPLIDAR
|
||||
bool begin(HardwareSerial &serialobj);
|
||||
|
||||
// close the currently opened serial interface
|
||||
void end();
|
||||
|
||||
// check whether the serial interface is opened
|
||||
bool isOpen();
|
||||
|
||||
// ask the RPLIDAR for its health info
|
||||
u_result getHealth(rplidar_response_device_health_t & healthinfo, _u32 timeout = RPLIDAR_DEFAULT_TIMEOUT);
|
||||
|
||||
// ask the RPLIDAR for its device info like the serial number
|
||||
u_result getDeviceInfo(rplidar_response_device_info_t & info, _u32 timeout = RPLIDAR_DEFAULT_TIMEOUT);
|
||||
|
||||
// stop the measurement operation
|
||||
u_result stop();
|
||||
|
||||
// start the measurement operation
|
||||
u_result startScan(bool force = false, _u32 timeout = RPLIDAR_DEFAULT_TIMEOUT*2);
|
||||
|
||||
// wait for one sample point to arrive
|
||||
u_result waitPoint(_u32 timeout = RPLIDAR_DEFAULT_TIMEOUT);
|
||||
|
||||
// retrieve currently received sample point
|
||||
|
||||
const RPLidarMeasurement & getCurrentPoint()
|
||||
{
|
||||
return _currentMeasurement;
|
||||
}
|
||||
|
||||
protected:
|
||||
u_result _sendCommand(_u8 cmd, const void * payload, size_t payloadsize);
|
||||
u_result _waitResponseHeader(rplidar_ans_header_t * header, _u32 timeout);
|
||||
|
||||
protected:
|
||||
HardwareSerial * _bined_serialdev;
|
||||
RPLidarMeasurement _currentMeasurement;
|
||||
};
|
||||
312
arduino/SPI.cpp
312
arduino/SPI.cpp
|
|
@ -1,312 +0,0 @@
|
|||
/*
|
||||
SPI.cpp - SPI library for esp8266
|
||||
|
||||
Copyright (c) 2015 Hristo Gochkov. All rights reserved.
|
||||
This file is part of the esp8266 core for Arduino environment.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "SPI.h"
|
||||
|
||||
SPIClass::SPIClass(uint8_t spi_bus)
|
||||
:_spi_num(spi_bus)
|
||||
,_spi(NULL)
|
||||
,_use_hw_ss(false)
|
||||
,_sck(-1)
|
||||
,_miso(-1)
|
||||
,_mosi(-1)
|
||||
,_ss(-1)
|
||||
,_div(0)
|
||||
,_freq(1000000)
|
||||
,_inTransaction(false)
|
||||
{}
|
||||
|
||||
void SPIClass::begin(int8_t sck, int8_t miso, int8_t mosi, int8_t ss)
|
||||
{
|
||||
if(_spi) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(!_div) {
|
||||
_div = spiFrequencyToClockDiv(_freq);
|
||||
}
|
||||
|
||||
_spi = spiStartBus(_spi_num, _div, SPI_MODE0, SPI_MSBFIRST);
|
||||
if(!_spi) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(sck == -1 && miso == -1 && mosi == -1 && ss == -1) {
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
_sck = (_spi_num == FSPI) ? SCK : -1;
|
||||
_miso = (_spi_num == FSPI) ? MISO : -1;
|
||||
_mosi = (_spi_num == FSPI) ? MOSI : -1;
|
||||
_ss = (_spi_num == FSPI) ? SS : -1;
|
||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||
_sck = SCK;
|
||||
_miso = MISO;
|
||||
_mosi = MOSI;
|
||||
_ss = SS;
|
||||
#else
|
||||
_sck = (_spi_num == VSPI) ? SCK : 14;
|
||||
_miso = (_spi_num == VSPI) ? MISO : 12;
|
||||
_mosi = (_spi_num == VSPI) ? MOSI : 13;
|
||||
_ss = (_spi_num == VSPI) ? SS : 15;
|
||||
#endif
|
||||
} else {
|
||||
_sck = sck;
|
||||
_miso = miso;
|
||||
_mosi = mosi;
|
||||
_ss = ss;
|
||||
}
|
||||
|
||||
spiAttachSCK(_spi, _sck);
|
||||
spiAttachMISO(_spi, _miso);
|
||||
spiAttachMOSI(_spi, _mosi);
|
||||
|
||||
}
|
||||
|
||||
void SPIClass::end()
|
||||
{
|
||||
if(!_spi) {
|
||||
return;
|
||||
}
|
||||
spiDetachSCK(_spi);
|
||||
spiDetachMISO(_spi);
|
||||
spiDetachMOSI(_spi);
|
||||
setHwCs(false);
|
||||
spiStopBus(_spi);
|
||||
_spi = NULL;
|
||||
}
|
||||
|
||||
void SPIClass::setHwCs(bool use)
|
||||
{
|
||||
if(use && !_use_hw_ss) {
|
||||
spiAttachSS(_spi, 0, _ss);
|
||||
spiSSEnable(_spi);
|
||||
} else if(!use && _use_hw_ss) {
|
||||
spiSSDisable(_spi);
|
||||
spiDetachSS(_spi);
|
||||
}
|
||||
_use_hw_ss = use;
|
||||
}
|
||||
|
||||
void SPIClass::setFrequency(uint32_t freq)
|
||||
{
|
||||
//check if last freq changed
|
||||
uint32_t cdiv = spiGetClockDiv(_spi);
|
||||
if(_freq != freq || _div != cdiv) {
|
||||
_freq = freq;
|
||||
_div = spiFrequencyToClockDiv(_freq);
|
||||
spiSetClockDiv(_spi, _div);
|
||||
}
|
||||
}
|
||||
|
||||
void SPIClass::setClockDivider(uint32_t clockDiv)
|
||||
{
|
||||
_div = clockDiv;
|
||||
spiSetClockDiv(_spi, _div);
|
||||
}
|
||||
|
||||
uint32_t SPIClass::getClockDivider()
|
||||
{
|
||||
return spiGetClockDiv(_spi);
|
||||
}
|
||||
|
||||
void SPIClass::setDataMode(uint8_t dataMode)
|
||||
{
|
||||
spiSetDataMode(_spi, dataMode);
|
||||
}
|
||||
|
||||
void SPIClass::setBitOrder(uint8_t bitOrder)
|
||||
{
|
||||
spiSetBitOrder(_spi, bitOrder);
|
||||
}
|
||||
|
||||
void SPIClass::beginTransaction(SPISettings settings)
|
||||
{
|
||||
//check if last freq changed
|
||||
uint32_t cdiv = spiGetClockDiv(_spi);
|
||||
if(_freq != settings._clock || _div != cdiv) {
|
||||
_freq = settings._clock;
|
||||
_div = spiFrequencyToClockDiv(_freq);
|
||||
}
|
||||
spiTransaction(_spi, _div, settings._dataMode, settings._bitOrder);
|
||||
_inTransaction = true;
|
||||
}
|
||||
|
||||
void SPIClass::endTransaction()
|
||||
{
|
||||
if(_inTransaction){
|
||||
_inTransaction = false;
|
||||
spiEndTransaction(_spi);
|
||||
}
|
||||
}
|
||||
|
||||
void SPIClass::write(uint8_t data)
|
||||
{
|
||||
if(_inTransaction){
|
||||
return spiWriteByteNL(_spi, data);
|
||||
}
|
||||
spiWriteByte(_spi, data);
|
||||
}
|
||||
|
||||
uint8_t SPIClass::transfer(uint8_t data)
|
||||
{
|
||||
if(_inTransaction){
|
||||
return spiTransferByteNL(_spi, data);
|
||||
}
|
||||
return spiTransferByte(_spi, data);
|
||||
}
|
||||
|
||||
void SPIClass::write16(uint16_t data)
|
||||
{
|
||||
if(_inTransaction){
|
||||
return spiWriteShortNL(_spi, data);
|
||||
}
|
||||
spiWriteWord(_spi, data);
|
||||
}
|
||||
|
||||
uint16_t SPIClass::transfer16(uint16_t data)
|
||||
{
|
||||
if(_inTransaction){
|
||||
return spiTransferShortNL(_spi, data);
|
||||
}
|
||||
return spiTransferWord(_spi, data);
|
||||
}
|
||||
|
||||
void SPIClass::write32(uint32_t data)
|
||||
{
|
||||
if(_inTransaction){
|
||||
return spiWriteLongNL(_spi, data);
|
||||
}
|
||||
spiWriteLong(_spi, data);
|
||||
}
|
||||
|
||||
uint32_t SPIClass::transfer32(uint32_t data)
|
||||
{
|
||||
if(_inTransaction){
|
||||
return spiTransferLongNL(_spi, data);
|
||||
}
|
||||
return spiTransferLong(_spi, data);
|
||||
}
|
||||
|
||||
void SPIClass::transferBits(uint32_t data, uint32_t * out, uint8_t bits)
|
||||
{
|
||||
if(_inTransaction){
|
||||
return spiTransferBitsNL(_spi, data, out, bits);
|
||||
}
|
||||
spiTransferBits(_spi, data, out, bits);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param data uint8_t *
|
||||
* @param size uint32_t
|
||||
*/
|
||||
void SPIClass::writeBytes(const uint8_t * data, uint32_t size)
|
||||
{
|
||||
if(_inTransaction){
|
||||
return spiWriteNL(_spi, data, size);
|
||||
}
|
||||
spiSimpleTransaction(_spi);
|
||||
spiWriteNL(_spi, data, size);
|
||||
spiEndTransaction(_spi);
|
||||
}
|
||||
|
||||
void SPIClass::transfer(uint8_t * data, uint32_t size)
|
||||
{
|
||||
transferBytes(data, data, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param data void *
|
||||
* @param size uint32_t
|
||||
*/
|
||||
void SPIClass::writePixels(const void * data, uint32_t size)
|
||||
{
|
||||
if(_inTransaction){
|
||||
return spiWritePixelsNL(_spi, data, size);
|
||||
}
|
||||
spiSimpleTransaction(_spi);
|
||||
spiWritePixelsNL(_spi, data, size);
|
||||
spiEndTransaction(_spi);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param data uint8_t * data buffer. can be NULL for Read Only operation
|
||||
* @param out uint8_t * output buffer. can be NULL for Write Only operation
|
||||
* @param size uint32_t
|
||||
*/
|
||||
void SPIClass::transferBytes(const uint8_t * data, uint8_t * out, uint32_t size)
|
||||
{
|
||||
if(_inTransaction){
|
||||
return spiTransferBytesNL(_spi, data, out, size);
|
||||
}
|
||||
spiTransferBytes(_spi, data, out, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param data uint8_t *
|
||||
* @param size uint8_t max for size is 64Byte
|
||||
* @param repeat uint32_t
|
||||
*/
|
||||
void SPIClass::writePattern(const uint8_t * data, uint8_t size, uint32_t repeat)
|
||||
{
|
||||
if(size > 64) {
|
||||
return; //max Hardware FIFO
|
||||
}
|
||||
|
||||
uint32_t byte = (size * repeat);
|
||||
uint8_t r = (64 / size);
|
||||
const uint8_t max_bytes_FIFO = r * size; // Max number of whole patterns (in bytes) that can fit into the hardware FIFO
|
||||
|
||||
while(byte) {
|
||||
if(byte > max_bytes_FIFO) {
|
||||
writePattern_(data, size, r);
|
||||
byte -= max_bytes_FIFO;
|
||||
} else {
|
||||
writePattern_(data, size, (byte / size));
|
||||
byte = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SPIClass::writePattern_(const uint8_t * data, uint8_t size, uint8_t repeat)
|
||||
{
|
||||
uint8_t bytes = (size * repeat);
|
||||
uint8_t buffer[64];
|
||||
uint8_t * bufferPtr = &buffer[0];
|
||||
const uint8_t * dataPtr;
|
||||
uint8_t dataSize = bytes;
|
||||
for(uint8_t i = 0; i < repeat; i++) {
|
||||
dataSize = size;
|
||||
dataPtr = data;
|
||||
while(dataSize--) {
|
||||
*bufferPtr = *dataPtr;
|
||||
dataPtr++;
|
||||
bufferPtr++;
|
||||
}
|
||||
}
|
||||
|
||||
writeBytes(&buffer[0], bytes);
|
||||
}
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
SPIClass SPI(VSPI);
|
||||
#else
|
||||
SPIClass SPI(FSPI);
|
||||
#endif
|
||||
|
||||
|
|
@ -1,91 +0,0 @@
|
|||
/*
|
||||
SPI.h - SPI library for esp32
|
||||
|
||||
Copyright (c) 2015 Hristo Gochkov. All rights reserved.
|
||||
This file is part of the esp8266 core for Arduino environment.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#ifndef _SPI_H_INCLUDED
|
||||
#define _SPI_H_INCLUDED
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "pins_arduino.h"
|
||||
#include "esp32-hal-spi.h"
|
||||
|
||||
#define SPI_HAS_TRANSACTION
|
||||
|
||||
class SPISettings
|
||||
{
|
||||
public:
|
||||
SPISettings() :_clock(1000000), _bitOrder(SPI_MSBFIRST), _dataMode(SPI_MODE0) {}
|
||||
SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) :_clock(clock), _bitOrder(bitOrder), _dataMode(dataMode) {}
|
||||
uint32_t _clock;
|
||||
uint8_t _bitOrder;
|
||||
uint8_t _dataMode;
|
||||
};
|
||||
|
||||
class SPIClass
|
||||
{
|
||||
private:
|
||||
int8_t _spi_num;
|
||||
spi_t * _spi;
|
||||
bool _use_hw_ss;
|
||||
int8_t _sck;
|
||||
int8_t _miso;
|
||||
int8_t _mosi;
|
||||
int8_t _ss;
|
||||
uint32_t _div;
|
||||
uint32_t _freq;
|
||||
bool _inTransaction;
|
||||
void writePattern_(const uint8_t * data, uint8_t size, uint8_t repeat);
|
||||
|
||||
public:
|
||||
SPIClass(uint8_t spi_bus=HSPI);
|
||||
void begin(int8_t sck=-1, int8_t miso=-1, int8_t mosi=-1, int8_t ss=-1);
|
||||
void end();
|
||||
|
||||
void setHwCs(bool use);
|
||||
void setBitOrder(uint8_t bitOrder);
|
||||
void setDataMode(uint8_t dataMode);
|
||||
void setFrequency(uint32_t freq);
|
||||
void setClockDivider(uint32_t clockDiv);
|
||||
|
||||
uint32_t getClockDivider();
|
||||
|
||||
void beginTransaction(SPISettings settings);
|
||||
void endTransaction(void);
|
||||
void transfer(uint8_t * data, uint32_t size);
|
||||
uint8_t transfer(uint8_t data);
|
||||
uint16_t transfer16(uint16_t data);
|
||||
uint32_t transfer32(uint32_t data);
|
||||
|
||||
void transferBytes(const uint8_t * data, uint8_t * out, uint32_t size);
|
||||
void transferBits(uint32_t data, uint32_t * out, uint8_t bits);
|
||||
|
||||
void write(uint8_t data);
|
||||
void write16(uint16_t data);
|
||||
void write32(uint32_t data);
|
||||
void writeBytes(const uint8_t * data, uint32_t size);
|
||||
void writePixels(const void * data, uint32_t size);//ili9341 compatible
|
||||
void writePattern(const uint8_t * data, uint8_t size, uint32_t repeat);
|
||||
|
||||
spi_t * bus(){ return _spi; }
|
||||
int8_t pinSS() { return _ss; }
|
||||
};
|
||||
|
||||
extern SPIClass SPI;
|
||||
|
||||
#endif
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
/*
|
||||
Server.h - Base class that provides Server
|
||||
Copyright (c) 2011 Adrian McEwen. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef server_h
|
||||
#define server_h
|
||||
|
||||
#include "Print.h"
|
||||
|
||||
class Server: public Print
|
||||
{
|
||||
public:
|
||||
virtual void begin(uint16_t port=0) =0;
|
||||
};
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,309 +0,0 @@
|
|||
/*
|
||||
This is a library written for the BNO080
|
||||
SparkFun sells these at its website: www.sparkfun.com
|
||||
Do you like this library? Help support SparkFun. Buy a board!
|
||||
https://www.sparkfun.com/products/14686
|
||||
|
||||
Written by Nathan Seidle @ SparkFun Electronics, December 28th, 2017
|
||||
|
||||
The BNO080 IMU is a powerful triple axis gyro/accel/magnetometer coupled with an ARM processor
|
||||
to maintain and complete all the complex calculations for various VR, inertial, step counting,
|
||||
and movement operations.
|
||||
|
||||
This library handles the initialization of the BNO080 and is able to query the sensor
|
||||
for different readings.
|
||||
|
||||
https://github.com/sparkfun/SparkFun_BNO080_Arduino_Library
|
||||
|
||||
Development environment specifics:
|
||||
Arduino IDE 1.8.3
|
||||
|
||||
SparkFun code, firmware, and software is released under the MIT License.
|
||||
Please see LICENSE.md for further details.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
#include "Wire.h"
|
||||
#include "SPI.h"
|
||||
|
||||
//The default I2C address for the BNO080 on the SparkX breakout is 0x4B. 0x4A is also possible.
|
||||
#define BNO080_DEFAULT_ADDRESS 0x4B
|
||||
|
||||
//Platform specific configurations
|
||||
|
||||
//Define the size of the I2C buffer based on the platform the user has
|
||||
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__)
|
||||
|
||||
//I2C_BUFFER_LENGTH is defined in Wire.H
|
||||
#ifndef I2C_BUFFER_LENGTH
|
||||
#define I2C_BUFFER_LENGTH BUFFER_LENGTH
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
//The catch-all default is 32
|
||||
#ifndef I2C_BUFFER_LENGTH
|
||||
#define I2C_BUFFER_LENGTH 32
|
||||
#endif
|
||||
|
||||
#endif
|
||||
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
//Registers
|
||||
const byte CHANNEL_COMMAND = 0;
|
||||
const byte CHANNEL_EXECUTABLE = 1;
|
||||
const byte CHANNEL_CONTROL = 2;
|
||||
const byte CHANNEL_REPORTS = 3;
|
||||
const byte CHANNEL_WAKE_REPORTS = 4;
|
||||
const byte CHANNEL_GYRO = 5;
|
||||
|
||||
//All the ways we can configure or talk to the BNO080, figure 34, page 36 reference manual
|
||||
//These are used for low level communication with the sensor, on channel 2
|
||||
#define SHTP_REPORT_COMMAND_RESPONSE 0xF1
|
||||
#define SHTP_REPORT_COMMAND_REQUEST 0xF2
|
||||
#define SHTP_REPORT_FRS_READ_RESPONSE 0xF3
|
||||
#define SHTP_REPORT_FRS_READ_REQUEST 0xF4
|
||||
#define SHTP_REPORT_PRODUCT_ID_RESPONSE 0xF8
|
||||
#define SHTP_REPORT_PRODUCT_ID_REQUEST 0xF9
|
||||
#define SHTP_REPORT_BASE_TIMESTAMP 0xFB
|
||||
#define SHTP_REPORT_SET_FEATURE_COMMAND 0xFD
|
||||
|
||||
//All the different sensors and features we can get reports from
|
||||
//These are used when enabling a given sensor
|
||||
#define SENSOR_REPORTID_ACCELEROMETER 0x01
|
||||
#define SENSOR_REPORTID_GYROSCOPE 0x02
|
||||
#define SENSOR_REPORTID_MAGNETIC_FIELD 0x03
|
||||
#define SENSOR_REPORTID_LINEAR_ACCELERATION 0x04
|
||||
#define SENSOR_REPORTID_ROTATION_VECTOR 0x05
|
||||
#define SENSOR_REPORTID_GRAVITY 0x06
|
||||
#define SENSOR_REPORTID_GAME_ROTATION_VECTOR 0x08
|
||||
#define SENSOR_REPORTID_GEOMAGNETIC_ROTATION_VECTOR 0x09
|
||||
#define SENSOR_REPORTID_GYRO_INTEGRATED_ROTATION_VECTOR 0x2A
|
||||
#define SENSOR_REPORTID_TAP_DETECTOR 0x10
|
||||
#define SENSOR_REPORTID_STEP_COUNTER 0x11
|
||||
#define SENSOR_REPORTID_STABILITY_CLASSIFIER 0x13
|
||||
#define SENSOR_REPORTID_RAW_ACCELEROMETER 0x14
|
||||
#define SENSOR_REPORTID_RAW_GYROSCOPE 0x15
|
||||
#define SENSOR_REPORTID_RAW_MAGNETOMETER 0x16
|
||||
#define SENSOR_REPORTID_PERSONAL_ACTIVITY_CLASSIFIER 0x1E
|
||||
#define SENSOR_REPORTID_AR_VR_STABILIZED_ROTATION_VECTOR 0x28
|
||||
#define SENSOR_REPORTID_AR_VR_STABILIZED_GAME_ROTATION_VECTOR 0x29
|
||||
|
||||
//Record IDs from figure 29, page 29 reference manual
|
||||
//These are used to read the metadata for each sensor type
|
||||
#define FRS_RECORDID_ACCELEROMETER 0xE302
|
||||
#define FRS_RECORDID_GYROSCOPE_CALIBRATED 0xE306
|
||||
#define FRS_RECORDID_MAGNETIC_FIELD_CALIBRATED 0xE309
|
||||
#define FRS_RECORDID_ROTATION_VECTOR 0xE30B
|
||||
|
||||
// Reset complete packet (BNO08X Datasheet p.24 Figure 1-27)
|
||||
#define EXECUTABLE_RESET_COMPLETE 0x1
|
||||
|
||||
//Command IDs from section 6.4, page 42
|
||||
//These are used to calibrate, initialize, set orientation, tare etc the sensor
|
||||
#define COMMAND_ERRORS 1
|
||||
#define COMMAND_COUNTER 2
|
||||
#define COMMAND_TARE 3
|
||||
#define COMMAND_INITIALIZE 4
|
||||
#define COMMAND_DCD 6
|
||||
#define COMMAND_ME_CALIBRATE 7
|
||||
#define COMMAND_DCD_PERIOD_SAVE 9
|
||||
#define COMMAND_OSCILLATOR 10
|
||||
#define COMMAND_CLEAR_DCD 11
|
||||
|
||||
#define CALIBRATE_ACCEL 0
|
||||
#define CALIBRATE_GYRO 1
|
||||
#define CALIBRATE_MAG 2
|
||||
#define CALIBRATE_PLANAR_ACCEL 3
|
||||
#define CALIBRATE_ACCEL_GYRO_MAG 4
|
||||
#define CALIBRATE_STOP 5
|
||||
|
||||
#define MAX_PACKET_SIZE 128 //Packets can be up to 32k but we don't have that much RAM.
|
||||
#define MAX_METADATA_SIZE 9 //This is in words. There can be many but we mostly only care about the first 9 (Qs, range, etc)
|
||||
|
||||
class BNO080
|
||||
{
|
||||
public:
|
||||
boolean begin(uint8_t deviceAddress = BNO080_DEFAULT_ADDRESS, TwoWire &wirePort = Wire, uint8_t intPin = 255); //By default use the default I2C addres, and use Wire port, and don't declare an INT pin
|
||||
boolean beginSPI(uint8_t user_CSPin, uint8_t user_WAKPin, uint8_t user_INTPin, uint8_t user_RSTPin, uint32_t spiPortSpeed = 3000000, SPIClass &spiPort = SPI);
|
||||
|
||||
void enableDebugging(Stream &debugPort = Serial); //Turn on debug printing. If user doesn't specify then Serial will be used.
|
||||
|
||||
void softReset(); //Try to reset the IMU via software
|
||||
bool hasReset(); //Returns true if the sensor has reported a reset. Reading this will unflag the reset.
|
||||
uint8_t resetReason(); //Query the IMU for the reason it last reset
|
||||
void modeOn(); //Use the executable channel to turn the BNO on
|
||||
void modeSleep(); //Use the executable channel to put the BNO to sleep
|
||||
|
||||
float qToFloat(int16_t fixedPointValue, uint8_t qPoint); //Given a Q value, converts fixed point floating to regular floating point number
|
||||
|
||||
boolean waitForI2C(); //Delay based polling for I2C traffic
|
||||
boolean waitForSPI(); //Delay based polling for INT pin to go low
|
||||
boolean receivePacket(void);
|
||||
boolean getData(uint16_t bytesRemaining); //Given a number of bytes, send the requests in I2C_BUFFER_LENGTH chunks
|
||||
boolean sendPacket(uint8_t channelNumber, uint8_t dataLength);
|
||||
void printPacket(void); //Prints the current shtp header and data packets
|
||||
void printHeader(void); //Prints the current shtp header (only)
|
||||
|
||||
void enableRotationVector(uint16_t timeBetweenReports);
|
||||
void enableGameRotationVector(uint16_t timeBetweenReports);
|
||||
void enableARVRStabilizedRotationVector(uint16_t timeBetweenReports);
|
||||
void enableARVRStabilizedGameRotationVector(uint16_t timeBetweenReports);
|
||||
void enableAccelerometer(uint16_t timeBetweenReports);
|
||||
void enableLinearAccelerometer(uint16_t timeBetweenReports);
|
||||
void enableGyro(uint16_t timeBetweenReports);
|
||||
void enableMagnetometer(uint16_t timeBetweenReports);
|
||||
void enableTapDetector(uint16_t timeBetweenReports);
|
||||
void enableStepCounter(uint16_t timeBetweenReports);
|
||||
void enableStabilityClassifier(uint16_t timeBetweenReports);
|
||||
void enableActivityClassifier(uint16_t timeBetweenReports, uint32_t activitiesToEnable, uint8_t (&activityConfidences)[9]);
|
||||
void enableRawAccelerometer(uint16_t timeBetweenReports);
|
||||
void enableRawGyro(uint16_t timeBetweenReports);
|
||||
void enableRawMagnetometer(uint16_t timeBetweenReports);
|
||||
void enableGyroIntegratedRotationVector(uint16_t timeBetweenReports);
|
||||
|
||||
bool dataAvailable(void);
|
||||
uint16_t getReadings(void);
|
||||
uint16_t parseInputReport(void); //Parse sensor readings out of report
|
||||
uint16_t parseCommandReport(void); //Parse command responses out of report
|
||||
|
||||
void getQuat(float &i, float &j, float &k, float &real, float &radAccuracy, uint8_t &accuracy);
|
||||
float getQuatI();
|
||||
float getQuatJ();
|
||||
float getQuatK();
|
||||
float getQuatReal();
|
||||
float getQuatRadianAccuracy();
|
||||
uint8_t getQuatAccuracy();
|
||||
|
||||
void getAccel(float &x, float &y, float &z, uint8_t &accuracy);
|
||||
float getAccelX();
|
||||
float getAccelY();
|
||||
float getAccelZ();
|
||||
uint8_t getAccelAccuracy();
|
||||
|
||||
void getLinAccel(float &x, float &y, float &z, uint8_t &accuracy);
|
||||
float getLinAccelX();
|
||||
float getLinAccelY();
|
||||
float getLinAccelZ();
|
||||
uint8_t getLinAccelAccuracy();
|
||||
|
||||
void getGyro(float &x, float &y, float &z, uint8_t &accuracy);
|
||||
float getGyroX();
|
||||
float getGyroY();
|
||||
float getGyroZ();
|
||||
uint8_t getGyroAccuracy();
|
||||
|
||||
void getFastGyro(float &x, float &y, float &z);
|
||||
float getFastGyroX();
|
||||
float getFastGyroY();
|
||||
float getFastGyroZ();
|
||||
|
||||
void getMag(float &x, float &y, float &z, uint8_t &accuracy);
|
||||
float getMagX();
|
||||
float getMagY();
|
||||
float getMagZ();
|
||||
uint8_t getMagAccuracy();
|
||||
|
||||
void calibrateAccelerometer();
|
||||
void calibrateGyro();
|
||||
void calibrateMagnetometer();
|
||||
void calibratePlanarAccelerometer();
|
||||
void calibrateAll();
|
||||
void endCalibration();
|
||||
void saveCalibration();
|
||||
void requestCalibrationStatus(); //Sends command to get status
|
||||
boolean calibrationComplete(); //Checks ME Cal response for byte 5, R0 - Status
|
||||
|
||||
uint8_t getTapDetector();
|
||||
uint32_t getTimeStamp();
|
||||
uint16_t getStepCount();
|
||||
uint8_t getStabilityClassifier();
|
||||
uint8_t getActivityClassifier();
|
||||
|
||||
int16_t getRawAccelX();
|
||||
int16_t getRawAccelY();
|
||||
int16_t getRawAccelZ();
|
||||
|
||||
int16_t getRawGyroX();
|
||||
int16_t getRawGyroY();
|
||||
int16_t getRawGyroZ();
|
||||
|
||||
int16_t getRawMagX();
|
||||
int16_t getRawMagY();
|
||||
int16_t getRawMagZ();
|
||||
|
||||
float getRoll();
|
||||
float getPitch();
|
||||
float getYaw();
|
||||
|
||||
void setFeatureCommand(uint8_t reportID, uint16_t timeBetweenReports);
|
||||
void setFeatureCommand(uint8_t reportID, uint16_t timeBetweenReports, uint32_t specificConfig);
|
||||
void sendCommand(uint8_t command);
|
||||
void sendCalibrateCommand(uint8_t thingToCalibrate);
|
||||
|
||||
//Metadata functions
|
||||
int16_t getQ1(uint16_t recordID);
|
||||
int16_t getQ2(uint16_t recordID);
|
||||
int16_t getQ3(uint16_t recordID);
|
||||
float getResolution(uint16_t recordID);
|
||||
float getRange(uint16_t recordID);
|
||||
uint32_t readFRSword(uint16_t recordID, uint8_t wordNumber);
|
||||
void frsReadRequest(uint16_t recordID, uint16_t readOffset, uint16_t blockSize);
|
||||
bool readFRSdata(uint16_t recordID, uint8_t startLocation, uint8_t wordsToRead);
|
||||
|
||||
//Global Variables
|
||||
uint8_t shtpHeader[4]; //Each packet has a header of 4 bytes
|
||||
uint8_t shtpData[MAX_PACKET_SIZE];
|
||||
uint8_t sequenceNumber[6] = {0, 0, 0, 0, 0, 0}; //There are 6 com channels. Each channel has its own seqnum
|
||||
uint8_t commandSequenceNumber = 0; //Commands have a seqNum as well. These are inside command packet, the header uses its own seqNum per channel
|
||||
uint32_t metaData[MAX_METADATA_SIZE]; //There is more than 10 words in a metadata record but we'll stop at Q point 3
|
||||
|
||||
private:
|
||||
//Variables
|
||||
TwoWire *_i2cPort; //The generic connection to user's chosen I2C hardware
|
||||
uint8_t _deviceAddress; //Keeps track of I2C address. setI2CAddress changes this.
|
||||
|
||||
Stream *_debugPort; //The stream to send debug messages to if enabled. Usually Serial.
|
||||
boolean _printDebug = false; //Flag to print debugging variables
|
||||
|
||||
SPIClass *_spiPort; //The generic connection to user's chosen SPI hardware
|
||||
unsigned long _spiPortSpeed; //Optional user defined port speed
|
||||
uint8_t _cs; //Pins needed for SPI
|
||||
uint8_t _wake;
|
||||
uint8_t _int;
|
||||
uint8_t _rst;
|
||||
|
||||
bool _hasReset = false; // Keeps track of any Reset Complete packets we receive.
|
||||
|
||||
//These are the raw sensor values (without Q applied) pulled from the user requested Input Report
|
||||
uint16_t rawAccelX, rawAccelY, rawAccelZ, accelAccuracy;
|
||||
uint16_t rawLinAccelX, rawLinAccelY, rawLinAccelZ, accelLinAccuracy;
|
||||
uint16_t rawGyroX, rawGyroY, rawGyroZ, gyroAccuracy;
|
||||
uint16_t rawMagX, rawMagY, rawMagZ, magAccuracy;
|
||||
uint16_t rawQuatI, rawQuatJ, rawQuatK, rawQuatReal, rawQuatRadianAccuracy, quatAccuracy;
|
||||
uint16_t rawFastGyroX, rawFastGyroY, rawFastGyroZ;
|
||||
uint8_t tapDetector;
|
||||
uint16_t stepCount;
|
||||
uint32_t timeStamp;
|
||||
uint8_t stabilityClassifier;
|
||||
uint8_t activityClassifier;
|
||||
uint8_t *_activityConfidences; //Array that store the confidences of the 9 possible activities
|
||||
uint8_t calibrationStatus; //Byte R0 of ME Calibration Response
|
||||
uint16_t memsRawAccelX, memsRawAccelY, memsRawAccelZ; //Raw readings from MEMS sensor
|
||||
uint16_t memsRawGyroX, memsRawGyroY, memsRawGyroZ; //Raw readings from MEMS sensor
|
||||
uint16_t memsRawMagX, memsRawMagY, memsRawMagZ; //Raw readings from MEMS sensor
|
||||
|
||||
//These Q values are defined in the datasheet but can also be obtained by querying the meta data records
|
||||
//See the read metadata example for more info
|
||||
int16_t rotationVector_Q1 = 14;
|
||||
int16_t rotationVectorAccuracy_Q1 = 12; //Heading accuracy estimate in radians. The Q point is 12.
|
||||
int16_t accelerometer_Q1 = 8;
|
||||
int16_t linear_accelerometer_Q1 = 8;
|
||||
int16_t gyro_Q1 = 9;
|
||||
int16_t magnetometer_Q1 = 4;
|
||||
int16_t angular_velocity_Q1 = 10;
|
||||
};
|
||||
|
|
@ -1,337 +0,0 @@
|
|||
/*
|
||||
Stream.cpp - adds parsing methods to Stream class
|
||||
Copyright (c) 2008 David A. Mellis. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Created July 2011
|
||||
parsing functions based on TextFinder library by Michael Margolis
|
||||
*/
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "Stream.h"
|
||||
#include "esp32-hal.h"
|
||||
|
||||
#define PARSE_TIMEOUT 1000 // default number of milli-seconds to wait
|
||||
#define NO_SKIP_CHAR 1 // a magic char not found in a valid ASCII numeric field
|
||||
|
||||
// private method to read stream with timeout
|
||||
int Stream::timedRead()
|
||||
{
|
||||
int c;
|
||||
_startMillis = millis();
|
||||
do {
|
||||
c = read();
|
||||
if(c >= 0) {
|
||||
return c;
|
||||
}
|
||||
} while(millis() - _startMillis < _timeout);
|
||||
return -1; // -1 indicates timeout
|
||||
}
|
||||
|
||||
// private method to peek stream with timeout
|
||||
int Stream::timedPeek()
|
||||
{
|
||||
int c;
|
||||
_startMillis = millis();
|
||||
do {
|
||||
c = peek();
|
||||
if(c >= 0) {
|
||||
return c;
|
||||
}
|
||||
} while(millis() - _startMillis < _timeout);
|
||||
return -1; // -1 indicates timeout
|
||||
}
|
||||
|
||||
// returns peek of the next digit in the stream or -1 if timeout
|
||||
// discards non-numeric characters
|
||||
int Stream::peekNextDigit()
|
||||
{
|
||||
int c;
|
||||
while(1) {
|
||||
c = timedPeek();
|
||||
if(c < 0) {
|
||||
return c; // timeout
|
||||
}
|
||||
if(c == '-') {
|
||||
return c;
|
||||
}
|
||||
if(c >= '0' && c <= '9') {
|
||||
return c;
|
||||
}
|
||||
read(); // discard non-numeric
|
||||
}
|
||||
}
|
||||
|
||||
// Public Methods
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
void Stream::setTimeout(unsigned long timeout) // sets the maximum number of milliseconds to wait
|
||||
{
|
||||
_timeout = timeout;
|
||||
}
|
||||
unsigned long Stream::getTimeout(void) {
|
||||
return _timeout;
|
||||
}
|
||||
|
||||
// find returns true if the target string is found
|
||||
bool Stream::find(const char *target)
|
||||
{
|
||||
return findUntil(target, strlen(target), NULL, 0);
|
||||
}
|
||||
|
||||
// reads data from the stream until the target string of given length is found
|
||||
// returns true if target string is found, false if timed out
|
||||
bool Stream::find(const char *target, size_t length)
|
||||
{
|
||||
return findUntil(target, length, NULL, 0);
|
||||
}
|
||||
|
||||
// as find but search ends if the terminator string is found
|
||||
bool Stream::findUntil(const char *target, const char *terminator)
|
||||
{
|
||||
return findUntil(target, strlen(target), terminator, strlen(terminator));
|
||||
}
|
||||
|
||||
// reads data from the stream until the target string of the given length is found
|
||||
// search terminated if the terminator string is found
|
||||
// returns true if target string is found, false if terminated or timed out
|
||||
bool Stream::findUntil(const char *target, size_t targetLen, const char *terminator, size_t termLen)
|
||||
{
|
||||
if (terminator == NULL) {
|
||||
MultiTarget t[1] = {{target, targetLen, 0}};
|
||||
return findMulti(t, 1) == 0 ? true : false;
|
||||
} else {
|
||||
MultiTarget t[2] = {{target, targetLen, 0}, {terminator, termLen, 0}};
|
||||
return findMulti(t, 2) == 0 ? true : false;
|
||||
}
|
||||
}
|
||||
|
||||
int Stream::findMulti( struct Stream::MultiTarget *targets, int tCount) {
|
||||
// any zero length target string automatically matches and would make
|
||||
// a mess of the rest of the algorithm.
|
||||
for (struct MultiTarget *t = targets; t < targets+tCount; ++t) {
|
||||
if (t->len <= 0)
|
||||
return t - targets;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
int c = timedRead();
|
||||
if (c < 0)
|
||||
return -1;
|
||||
|
||||
for (struct MultiTarget *t = targets; t < targets+tCount; ++t) {
|
||||
// the simple case is if we match, deal with that first.
|
||||
if (c == t->str[t->index]) {
|
||||
if (++t->index == t->len)
|
||||
return t - targets;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
|
||||
// if not we need to walk back and see if we could have matched further
|
||||
// down the stream (ie '1112' doesn't match the first position in '11112'
|
||||
// but it will match the second position so we can't just reset the current
|
||||
// index to 0 when we find a mismatch.
|
||||
if (t->index == 0)
|
||||
continue;
|
||||
|
||||
int origIndex = t->index;
|
||||
do {
|
||||
--t->index;
|
||||
// first check if current char works against the new current index
|
||||
if (c != t->str[t->index])
|
||||
continue;
|
||||
|
||||
// if it's the only char then we're good, nothing more to check
|
||||
if (t->index == 0) {
|
||||
t->index++;
|
||||
break;
|
||||
}
|
||||
|
||||
// otherwise we need to check the rest of the found string
|
||||
int diff = origIndex - t->index;
|
||||
size_t i;
|
||||
for (i = 0; i < t->index; ++i) {
|
||||
if (t->str[i] != t->str[i + diff])
|
||||
break;
|
||||
}
|
||||
|
||||
// if we successfully got through the previous loop then our current
|
||||
// index is good.
|
||||
if (i == t->index) {
|
||||
t->index++;
|
||||
break;
|
||||
}
|
||||
|
||||
// otherwise we just try the next index
|
||||
} while (t->index);
|
||||
}
|
||||
}
|
||||
// unreachable
|
||||
return -1;
|
||||
}
|
||||
|
||||
// returns the first valid (long) integer value from the current position.
|
||||
// initial characters that are not digits (or the minus sign) are skipped
|
||||
// function is terminated by the first character that is not a digit.
|
||||
long Stream::parseInt()
|
||||
{
|
||||
return parseInt(NO_SKIP_CHAR); // terminate on first non-digit character (or timeout)
|
||||
}
|
||||
|
||||
// as above but a given skipChar is ignored
|
||||
// this allows format characters (typically commas) in values to be ignored
|
||||
long Stream::parseInt(char skipChar)
|
||||
{
|
||||
boolean isNegative = false;
|
||||
long value = 0;
|
||||
int c;
|
||||
|
||||
c = peekNextDigit();
|
||||
// ignore non numeric leading characters
|
||||
if(c < 0) {
|
||||
return 0; // zero returned if timeout
|
||||
}
|
||||
|
||||
do {
|
||||
if(c == skipChar) {
|
||||
} // ignore this charactor
|
||||
else if(c == '-') {
|
||||
isNegative = true;
|
||||
} else if(c >= '0' && c <= '9') { // is c a digit?
|
||||
value = value * 10 + c - '0';
|
||||
}
|
||||
read(); // consume the character we got with peek
|
||||
c = timedPeek();
|
||||
} while((c >= '0' && c <= '9') || c == skipChar);
|
||||
|
||||
if(isNegative) {
|
||||
value = -value;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
// as parseInt but returns a floating point value
|
||||
float Stream::parseFloat()
|
||||
{
|
||||
return parseFloat(NO_SKIP_CHAR);
|
||||
}
|
||||
|
||||
// as above but the given skipChar is ignored
|
||||
// this allows format characters (typically commas) in values to be ignored
|
||||
float Stream::parseFloat(char skipChar)
|
||||
{
|
||||
boolean isNegative = false;
|
||||
boolean isFraction = false;
|
||||
long value = 0;
|
||||
int c;
|
||||
float fraction = 1.0;
|
||||
|
||||
c = peekNextDigit();
|
||||
// ignore non numeric leading characters
|
||||
if(c < 0) {
|
||||
return 0; // zero returned if timeout
|
||||
}
|
||||
|
||||
do {
|
||||
if(c == skipChar) {
|
||||
} // ignore
|
||||
else if(c == '-') {
|
||||
isNegative = true;
|
||||
} else if(c == '.') {
|
||||
isFraction = true;
|
||||
} else if(c >= '0' && c <= '9') { // is c a digit?
|
||||
value = value * 10 + c - '0';
|
||||
if(isFraction) {
|
||||
fraction *= 0.1f;
|
||||
}
|
||||
}
|
||||
read(); // consume the character we got with peek
|
||||
c = timedPeek();
|
||||
} while((c >= '0' && c <= '9') || c == '.' || c == skipChar);
|
||||
|
||||
if(isNegative) {
|
||||
value = -value;
|
||||
}
|
||||
if(isFraction) {
|
||||
return value * fraction;
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
// read characters from stream into buffer
|
||||
// terminates if length characters have been read, or timeout (see setTimeout)
|
||||
// returns the number of characters placed in the buffer
|
||||
// the buffer is NOT null terminated.
|
||||
//
|
||||
size_t Stream::readBytes(char *buffer, size_t length)
|
||||
{
|
||||
size_t count = 0;
|
||||
while(count < length) {
|
||||
int c = timedRead();
|
||||
if(c < 0) {
|
||||
break;
|
||||
}
|
||||
*buffer++ = (char) c;
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
// as readBytes with terminator character
|
||||
// terminates if length characters have been read, timeout, or if the terminator character detected
|
||||
// returns the number of characters placed in the buffer (0 means no valid data found)
|
||||
|
||||
size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length)
|
||||
{
|
||||
if(length < 1) {
|
||||
return 0;
|
||||
}
|
||||
size_t index = 0;
|
||||
while(index < length) {
|
||||
int c = timedRead();
|
||||
if(c < 0 || c == terminator) {
|
||||
break;
|
||||
}
|
||||
*buffer++ = (char) c;
|
||||
index++;
|
||||
}
|
||||
return index; // return number of characters, not including null terminator
|
||||
}
|
||||
|
||||
String Stream::readString()
|
||||
{
|
||||
String ret;
|
||||
int c = timedRead();
|
||||
while(c >= 0) {
|
||||
ret += (char) c;
|
||||
c = timedRead();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
String Stream::readStringUntil(char terminator)
|
||||
{
|
||||
String ret;
|
||||
int c = timedRead();
|
||||
while(c >= 0 && c != terminator) {
|
||||
ret += (char) c;
|
||||
c = timedRead();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
140
arduino/Stream.h
140
arduino/Stream.h
|
|
@ -1,140 +0,0 @@
|
|||
/*
|
||||
Stream.h - base class for character-based streams.
|
||||
Copyright (c) 2010 David A. Mellis. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
parsing functions based on TextFinder library by Michael Margolis
|
||||
*/
|
||||
|
||||
#ifndef Stream_h
|
||||
#define Stream_h
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "Print.h"
|
||||
|
||||
// compatability macros for testing
|
||||
/*
|
||||
#define getInt() parseInt()
|
||||
#define getInt(skipChar) parseInt(skipchar)
|
||||
#define getFloat() parseFloat()
|
||||
#define getFloat(skipChar) parseFloat(skipChar)
|
||||
#define getString( pre_string, post_string, buffer, length)
|
||||
readBytesBetween( pre_string, terminator, buffer, length)
|
||||
*/
|
||||
|
||||
class Stream: public Print
|
||||
{
|
||||
protected:
|
||||
unsigned long _timeout; // number of milliseconds to wait for the next char before aborting timed read
|
||||
unsigned long _startMillis; // used for timeout measurement
|
||||
int timedRead(); // private method to read stream with timeout
|
||||
int timedPeek(); // private method to peek stream with timeout
|
||||
int peekNextDigit(); // returns the next numeric digit in the stream or -1 if timeout
|
||||
|
||||
public:
|
||||
virtual int available() = 0;
|
||||
virtual int read() = 0;
|
||||
virtual int peek() = 0;
|
||||
virtual void flush() = 0;
|
||||
|
||||
Stream():_startMillis(0)
|
||||
{
|
||||
_timeout = 1000;
|
||||
}
|
||||
virtual ~Stream() {}
|
||||
|
||||
// parsing methods
|
||||
|
||||
void setTimeout(unsigned long timeout); // sets maximum milliseconds to wait for stream data, default is 1 second
|
||||
unsigned long getTimeout(void);
|
||||
|
||||
bool find(const char *target); // reads data from the stream until the target string is found
|
||||
bool find(uint8_t *target)
|
||||
{
|
||||
return find((char *) target);
|
||||
}
|
||||
// returns true if target string is found, false if timed out (see setTimeout)
|
||||
|
||||
bool find(const char *target, size_t length); // reads data from the stream until the target string of given length is found
|
||||
bool find(const uint8_t *target, size_t length)
|
||||
{
|
||||
return find((char *) target, length);
|
||||
}
|
||||
// returns true if target string is found, false if timed out
|
||||
|
||||
bool find(char target)
|
||||
{
|
||||
return find (&target, 1);
|
||||
}
|
||||
|
||||
bool findUntil(const char *target, const char *terminator); // as find but search ends if the terminator string is found
|
||||
bool findUntil(const uint8_t *target, const char *terminator)
|
||||
{
|
||||
return findUntil((char *) target, terminator);
|
||||
}
|
||||
|
||||
bool findUntil(const char *target, size_t targetLen, const char *terminate, size_t termLen); // as above but search ends if the terminate string is found
|
||||
bool findUntil(const uint8_t *target, size_t targetLen, const char *terminate, size_t termLen)
|
||||
{
|
||||
return findUntil((char *) target, targetLen, terminate, termLen);
|
||||
}
|
||||
|
||||
long parseInt(); // returns the first valid (long) integer value from the current position.
|
||||
// initial characters that are not digits (or the minus sign) are skipped
|
||||
// integer is terminated by the first character that is not a digit.
|
||||
|
||||
float parseFloat(); // float version of parseInt
|
||||
|
||||
virtual size_t readBytes(char *buffer, size_t length); // read chars from stream into buffer
|
||||
virtual size_t readBytes(uint8_t *buffer, size_t length)
|
||||
{
|
||||
return readBytes((char *) buffer, length);
|
||||
}
|
||||
// terminates if length characters have been read or timeout (see setTimeout)
|
||||
// returns the number of characters placed in the buffer (0 means no valid data found)
|
||||
|
||||
size_t readBytesUntil(char terminator, char *buffer, size_t length); // as readBytes with terminator character
|
||||
size_t readBytesUntil(char terminator, uint8_t *buffer, size_t length)
|
||||
{
|
||||
return readBytesUntil(terminator, (char *) buffer, length);
|
||||
}
|
||||
// terminates if length characters have been read, timeout, or if the terminator character detected
|
||||
// returns the number of characters placed in the buffer (0 means no valid data found)
|
||||
|
||||
// Arduino String functions to be added here
|
||||
virtual String readString();
|
||||
String readStringUntil(char terminator);
|
||||
|
||||
protected:
|
||||
long parseInt(char skipChar); // as above but the given skipChar is ignored
|
||||
// as above but the given skipChar is ignored
|
||||
// this allows format characters (typically commas) in values to be ignored
|
||||
|
||||
float parseFloat(char skipChar); // as above but the given skipChar is ignored
|
||||
|
||||
struct MultiTarget {
|
||||
const char *str; // string you're searching for
|
||||
size_t len; // length of string you're searching for
|
||||
size_t index; // index used by the search routine.
|
||||
};
|
||||
|
||||
// This allows you to search for an arbitrary number of strings.
|
||||
// Returns index of the target that is found first or -1 if timeout occurs.
|
||||
int findMulti(struct MultiTarget *targets, int tCount);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -1,439 +0,0 @@
|
|||
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// 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.
|
||||
|
||||
#include "USBCDC.h"
|
||||
|
||||
#if SOC_USB_OTG_SUPPORTED
|
||||
#include "USB.h"
|
||||
#if CONFIG_TINYUSB_CDC_ENABLED
|
||||
|
||||
#include "esp32-hal-tinyusb.h"
|
||||
#include "rom/ets_sys.h"
|
||||
|
||||
ESP_EVENT_DEFINE_BASE(ARDUINO_USB_CDC_EVENTS);
|
||||
esp_err_t arduino_usb_event_post(esp_event_base_t event_base, int32_t event_id, void *event_data, size_t event_data_size, TickType_t ticks_to_wait);
|
||||
esp_err_t arduino_usb_event_handler_register_with(esp_event_base_t event_base, int32_t event_id, esp_event_handler_t event_handler, void *event_handler_arg);
|
||||
|
||||
#define MAX_USB_CDC_DEVICES 2
|
||||
USBCDC *devices[MAX_USB_CDC_DEVICES] = {NULL, NULL};
|
||||
|
||||
static uint16_t load_cdc_descriptor(uint8_t *dst, uint8_t *itf) {
|
||||
uint8_t str_index = tinyusb_add_string_descriptor("TinyUSB CDC");
|
||||
uint8_t descriptor[TUD_CDC_DESC_LEN] = {// Interface number, string index, EP notification address and size, EP data address (out, in) and size.
|
||||
TUD_CDC_DESCRIPTOR(*itf, str_index, 0x85, 64, 0x03, 0x84, 64)
|
||||
};
|
||||
*itf += 2;
|
||||
memcpy(dst, descriptor, TUD_CDC_DESC_LEN);
|
||||
return TUD_CDC_DESC_LEN;
|
||||
}
|
||||
|
||||
// Invoked when line state DTR & RTS are changed via SET_CONTROL_LINE_STATE
|
||||
void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) {
|
||||
if (itf < MAX_USB_CDC_DEVICES && devices[itf] != NULL) {
|
||||
devices[itf]->_onLineState(dtr, rts);
|
||||
}
|
||||
}
|
||||
|
||||
// Invoked when line coding is change via SET_LINE_CODING
|
||||
void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const *p_line_coding) {
|
||||
if (itf < MAX_USB_CDC_DEVICES && devices[itf] != NULL) {
|
||||
devices[itf]->_onLineCoding(p_line_coding->bit_rate, p_line_coding->stop_bits, p_line_coding->parity, p_line_coding->data_bits);
|
||||
}
|
||||
}
|
||||
|
||||
// Invoked when received new data
|
||||
void tud_cdc_rx_cb(uint8_t itf) {
|
||||
if (itf < MAX_USB_CDC_DEVICES && devices[itf] != NULL) {
|
||||
devices[itf]->_onRX();
|
||||
}
|
||||
}
|
||||
|
||||
// Invoked when received send break
|
||||
void tud_cdc_send_break_cb(uint8_t itf, uint16_t duration_ms) {
|
||||
//log_v("itf: %u, duration_ms: %u", itf, duration_ms);
|
||||
}
|
||||
|
||||
// Invoked when space becomes available in TX buffer
|
||||
void tud_cdc_tx_complete_cb(uint8_t itf) {
|
||||
if (itf < MAX_USB_CDC_DEVICES && devices[itf] != NULL) {
|
||||
devices[itf]->_onTX();
|
||||
}
|
||||
}
|
||||
|
||||
static void ARDUINO_ISR_ATTR cdc0_write_char(char c) {
|
||||
if (devices[0] != NULL) {
|
||||
tud_cdc_n_write_char(0, c);
|
||||
}
|
||||
}
|
||||
|
||||
static void usb_unplugged_cb(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) {
|
||||
((USBCDC *)arg)->_onUnplugged();
|
||||
}
|
||||
|
||||
USBCDC::USBCDC(uint8_t itfn)
|
||||
: itf(itfn), bit_rate(0), stop_bits(0), parity(0), data_bits(0), dtr(false), rts(false), connected(false), reboot_enable(true), rx_queue(NULL), tx_lock(NULL),
|
||||
tx_timeout_ms(250) {
|
||||
tinyusb_enable_interface(USB_INTERFACE_CDC, TUD_CDC_DESC_LEN, load_cdc_descriptor);
|
||||
if (itf < MAX_USB_CDC_DEVICES) {
|
||||
arduino_usb_event_handler_register_with(ARDUINO_USB_EVENTS, ARDUINO_USB_STOPPED_EVENT, usb_unplugged_cb, this);
|
||||
}
|
||||
}
|
||||
|
||||
USBCDC::~USBCDC() {
|
||||
end();
|
||||
}
|
||||
|
||||
void USBCDC::onEvent(esp_event_handler_t callback) {
|
||||
onEvent(ARDUINO_USB_CDC_ANY_EVENT, callback);
|
||||
}
|
||||
void USBCDC::onEvent(arduino_usb_cdc_event_t event, esp_event_handler_t callback) {
|
||||
arduino_usb_event_handler_register_with(ARDUINO_USB_CDC_EVENTS, event, callback, this);
|
||||
}
|
||||
|
||||
size_t USBCDC::setRxBufferSize(size_t rx_queue_len) {
|
||||
size_t currentQueueSize = rx_queue ? uxQueueSpacesAvailable(rx_queue) + uxQueueMessagesWaiting(rx_queue) : 0;
|
||||
|
||||
if (rx_queue_len != currentQueueSize) {
|
||||
QueueHandle_t new_rx_queue = NULL;
|
||||
if (rx_queue_len) {
|
||||
new_rx_queue = xQueueCreate(rx_queue_len, sizeof(uint8_t));
|
||||
if (!new_rx_queue) {
|
||||
log_e("CDC Queue creation failed.");
|
||||
return 0;
|
||||
}
|
||||
if (rx_queue) {
|
||||
size_t copySize = uxQueueMessagesWaiting(rx_queue);
|
||||
if (copySize > 0) {
|
||||
for (size_t i = 0; i < copySize; i++) {
|
||||
uint8_t ch = 0;
|
||||
xQueueReceive(rx_queue, &ch, 0);
|
||||
if (!xQueueSend(new_rx_queue, &ch, 0)) {
|
||||
arduino_usb_cdc_event_data_t p;
|
||||
p.rx_overflow.dropped_bytes = copySize - i;
|
||||
arduino_usb_event_post(ARDUINO_USB_CDC_EVENTS, ARDUINO_USB_CDC_RX_OVERFLOW_EVENT, &p, sizeof(arduino_usb_cdc_event_data_t), portMAX_DELAY);
|
||||
log_e("CDC RX Overflow.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
vQueueDelete(rx_queue);
|
||||
}
|
||||
rx_queue = new_rx_queue;
|
||||
return rx_queue_len;
|
||||
} else {
|
||||
if (rx_queue) {
|
||||
vQueueDelete(rx_queue);
|
||||
rx_queue = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
return rx_queue_len;
|
||||
}
|
||||
|
||||
void USBCDC::begin(unsigned long baud) {
|
||||
if (tx_lock == NULL) {
|
||||
tx_lock = xSemaphoreCreateMutex();
|
||||
}
|
||||
// if rx_queue was set before begin(), keep it
|
||||
if (!rx_queue) {
|
||||
setRxBufferSize(256); //default if not preset
|
||||
}
|
||||
devices[itf] = this;
|
||||
}
|
||||
|
||||
void USBCDC::end() {
|
||||
connected = false;
|
||||
devices[itf] = NULL;
|
||||
setRxBufferSize(0);
|
||||
if (tx_lock != NULL) {
|
||||
vSemaphoreDelete(tx_lock);
|
||||
tx_lock = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void USBCDC::setTxTimeoutMs(uint32_t timeout) {
|
||||
tx_timeout_ms = timeout;
|
||||
}
|
||||
|
||||
void USBCDC::_onUnplugged(void) {
|
||||
if (connected) {
|
||||
connected = false;
|
||||
dtr = false;
|
||||
rts = false;
|
||||
arduino_usb_cdc_event_data_t p;
|
||||
arduino_usb_event_post(ARDUINO_USB_CDC_EVENTS, ARDUINO_USB_CDC_DISCONNECTED_EVENT, &p, sizeof(arduino_usb_cdc_event_data_t), portMAX_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
enum {
|
||||
CDC_LINE_IDLE,
|
||||
CDC_LINE_1,
|
||||
CDC_LINE_2,
|
||||
CDC_LINE_3
|
||||
};
|
||||
void USBCDC::_onLineState(bool _dtr, bool _rts) {
|
||||
static uint8_t lineState = CDC_LINE_IDLE;
|
||||
|
||||
if (dtr == _dtr && rts == _rts) {
|
||||
return; // Skip duplicate events
|
||||
}
|
||||
|
||||
dtr = _dtr;
|
||||
rts = _rts;
|
||||
|
||||
if (reboot_enable) {
|
||||
if (!dtr && rts) {
|
||||
if (lineState == CDC_LINE_IDLE) {
|
||||
lineState++;
|
||||
if (connected) {
|
||||
connected = false;
|
||||
arduino_usb_cdc_event_data_t p;
|
||||
arduino_usb_event_post(ARDUINO_USB_CDC_EVENTS, ARDUINO_USB_CDC_DISCONNECTED_EVENT, &p, sizeof(arduino_usb_cdc_event_data_t), portMAX_DELAY);
|
||||
}
|
||||
// } else if(lineState == CDC_LINE_2){//esptool.js
|
||||
// lineState++;
|
||||
} else {
|
||||
lineState = CDC_LINE_IDLE;
|
||||
}
|
||||
} else if (dtr && rts) {
|
||||
if (lineState == CDC_LINE_1) {
|
||||
lineState++;
|
||||
} else {
|
||||
lineState = CDC_LINE_IDLE;
|
||||
}
|
||||
} else if (dtr && !rts) {
|
||||
if (lineState == CDC_LINE_2) {
|
||||
lineState++;
|
||||
// } else if(lineState == CDC_LINE_IDLE){//esptool.js
|
||||
// lineState++;
|
||||
} else {
|
||||
lineState = CDC_LINE_IDLE;
|
||||
}
|
||||
} else if (!dtr && !rts) {
|
||||
if (lineState == CDC_LINE_3) {
|
||||
usb_persist_restart(RESTART_BOOTLOADER);
|
||||
} else {
|
||||
lineState = CDC_LINE_IDLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (lineState == CDC_LINE_IDLE) {
|
||||
if (dtr && rts && !connected) {
|
||||
connected = true;
|
||||
arduino_usb_cdc_event_data_t p;
|
||||
arduino_usb_event_post(ARDUINO_USB_CDC_EVENTS, ARDUINO_USB_CDC_CONNECTED_EVENT, &p, sizeof(arduino_usb_cdc_event_data_t), portMAX_DELAY);
|
||||
} else if (!dtr && connected) {
|
||||
connected = false;
|
||||
arduino_usb_cdc_event_data_t p;
|
||||
arduino_usb_event_post(ARDUINO_USB_CDC_EVENTS, ARDUINO_USB_CDC_DISCONNECTED_EVENT, &p, sizeof(arduino_usb_cdc_event_data_t), portMAX_DELAY);
|
||||
}
|
||||
arduino_usb_cdc_event_data_t l;
|
||||
l.line_state.dtr = dtr;
|
||||
l.line_state.rts = rts;
|
||||
arduino_usb_event_post(ARDUINO_USB_CDC_EVENTS, ARDUINO_USB_CDC_LINE_STATE_EVENT, &l, sizeof(arduino_usb_cdc_event_data_t), portMAX_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
void USBCDC::_onLineCoding(uint32_t _bit_rate, uint8_t _stop_bits, uint8_t _parity, uint8_t _data_bits) {
|
||||
if (bit_rate != _bit_rate || data_bits != _data_bits || stop_bits != _stop_bits || parity != _parity) {
|
||||
// ArduinoIDE sends LineCoding with 1200bps baud to reset the device
|
||||
if (reboot_enable && _bit_rate == 1200) {
|
||||
usb_persist_restart(RESTART_BOOTLOADER);
|
||||
} else {
|
||||
bit_rate = _bit_rate;
|
||||
data_bits = _data_bits;
|
||||
stop_bits = _stop_bits;
|
||||
parity = _parity;
|
||||
arduino_usb_cdc_event_data_t p;
|
||||
p.line_coding.bit_rate = bit_rate;
|
||||
p.line_coding.data_bits = data_bits;
|
||||
p.line_coding.stop_bits = stop_bits;
|
||||
p.line_coding.parity = parity;
|
||||
arduino_usb_event_post(ARDUINO_USB_CDC_EVENTS, ARDUINO_USB_CDC_LINE_CODING_EVENT, &p, sizeof(arduino_usb_cdc_event_data_t), portMAX_DELAY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void USBCDC::_onRX() {
|
||||
arduino_usb_cdc_event_data_t p;
|
||||
uint8_t buf[CONFIG_TINYUSB_CDC_RX_BUFSIZE + 1];
|
||||
uint32_t count = tud_cdc_n_read(itf, buf, CONFIG_TINYUSB_CDC_RX_BUFSIZE);
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
if (rx_queue == NULL || !xQueueSend(rx_queue, buf + i, 10)) {
|
||||
p.rx_overflow.dropped_bytes = count - i;
|
||||
arduino_usb_event_post(ARDUINO_USB_CDC_EVENTS, ARDUINO_USB_CDC_RX_OVERFLOW_EVENT, &p, sizeof(arduino_usb_cdc_event_data_t), portMAX_DELAY);
|
||||
log_e("CDC RX Overflow.");
|
||||
count = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (count) {
|
||||
p.rx.len = count;
|
||||
arduino_usb_event_post(ARDUINO_USB_CDC_EVENTS, ARDUINO_USB_CDC_RX_EVENT, &p, sizeof(arduino_usb_cdc_event_data_t), portMAX_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
void USBCDC::_onTX() {
|
||||
arduino_usb_cdc_event_data_t p;
|
||||
arduino_usb_event_post(ARDUINO_USB_CDC_EVENTS, ARDUINO_USB_CDC_TX_EVENT, &p, sizeof(arduino_usb_cdc_event_data_t), portMAX_DELAY);
|
||||
}
|
||||
|
||||
void USBCDC::enableReboot(bool enable) {
|
||||
reboot_enable = enable;
|
||||
}
|
||||
bool USBCDC::rebootEnabled(void) {
|
||||
return reboot_enable;
|
||||
}
|
||||
|
||||
int USBCDC::available(void) {
|
||||
if (itf >= MAX_USB_CDC_DEVICES || rx_queue == NULL) {
|
||||
return -1;
|
||||
}
|
||||
return uxQueueMessagesWaiting(rx_queue);
|
||||
}
|
||||
|
||||
int USBCDC::peek(void) {
|
||||
if (itf >= MAX_USB_CDC_DEVICES || rx_queue == NULL) {
|
||||
return -1;
|
||||
}
|
||||
uint8_t c;
|
||||
if (xQueuePeek(rx_queue, &c, 0)) {
|
||||
return c;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int USBCDC::read(void) {
|
||||
if (itf >= MAX_USB_CDC_DEVICES || rx_queue == NULL) {
|
||||
return -1;
|
||||
}
|
||||
uint8_t c = 0;
|
||||
if (xQueueReceive(rx_queue, &c, 0)) {
|
||||
return c;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t USBCDC::read(uint8_t *buffer, size_t size) {
|
||||
if (itf >= MAX_USB_CDC_DEVICES || rx_queue == NULL) {
|
||||
return -1;
|
||||
}
|
||||
uint8_t c = 0;
|
||||
size_t count = 0;
|
||||
while (count < size && xQueueReceive(rx_queue, &c, 0)) {
|
||||
buffer[count++] = c;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
void USBCDC::flush(void) {
|
||||
if (itf >= MAX_USB_CDC_DEVICES || tx_lock == NULL || !tud_cdc_n_connected(itf)) {
|
||||
return;
|
||||
}
|
||||
if (xSemaphoreTake(tx_lock, tx_timeout_ms / portTICK_PERIOD_MS) != pdPASS) {
|
||||
return;
|
||||
}
|
||||
tud_cdc_n_write_flush(itf);
|
||||
xSemaphoreGive(tx_lock);
|
||||
}
|
||||
|
||||
int USBCDC::availableForWrite(void) {
|
||||
if (itf >= MAX_USB_CDC_DEVICES || tx_lock == NULL || !tud_cdc_n_connected(itf)) {
|
||||
return 0;
|
||||
}
|
||||
if (xSemaphoreTake(tx_lock, tx_timeout_ms / portTICK_PERIOD_MS) != pdPASS) {
|
||||
return 0;
|
||||
}
|
||||
size_t a = tud_cdc_n_write_available(itf);
|
||||
xSemaphoreGive(tx_lock);
|
||||
return a;
|
||||
}
|
||||
|
||||
size_t USBCDC::write(const uint8_t *buffer, size_t size) {
|
||||
if (itf >= MAX_USB_CDC_DEVICES || tx_lock == NULL || buffer == NULL || size == 0 || !tud_cdc_n_connected(itf)) {
|
||||
return 0;
|
||||
}
|
||||
if (xPortInIsrContext()) {
|
||||
BaseType_t taskWoken = false;
|
||||
if (xSemaphoreTakeFromISR(tx_lock, &taskWoken) != pdPASS) {
|
||||
return 0;
|
||||
}
|
||||
} else if (xSemaphoreTake(tx_lock, tx_timeout_ms / portTICK_PERIOD_MS) != pdPASS) {
|
||||
return 0;
|
||||
}
|
||||
size_t to_send = size, so_far = 0;
|
||||
while (to_send) {
|
||||
if (!tud_cdc_n_connected(itf)) {
|
||||
size = so_far;
|
||||
break;
|
||||
}
|
||||
size_t space = tud_cdc_n_write_available(itf);
|
||||
if (!space) {
|
||||
tud_cdc_n_write_flush(itf);
|
||||
continue;
|
||||
}
|
||||
if (space > to_send) {
|
||||
space = to_send;
|
||||
}
|
||||
size_t sent = tud_cdc_n_write(itf, buffer + so_far, space);
|
||||
if (sent) {
|
||||
so_far += sent;
|
||||
to_send -= sent;
|
||||
tud_cdc_n_write_flush(itf);
|
||||
} else {
|
||||
size = so_far;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (xPortInIsrContext()) {
|
||||
BaseType_t taskWoken = false;
|
||||
xSemaphoreGiveFromISR(tx_lock, &taskWoken);
|
||||
} else {
|
||||
xSemaphoreGive(tx_lock);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
size_t USBCDC::write(uint8_t c) {
|
||||
return write(&c, 1);
|
||||
}
|
||||
|
||||
uint32_t USBCDC::baudRate() {
|
||||
return bit_rate;
|
||||
}
|
||||
|
||||
void USBCDC::setDebugOutput(bool en) {
|
||||
if (en) {
|
||||
uartSetDebug(NULL);
|
||||
ets_install_putc2((void (*)(char)) & cdc0_write_char);
|
||||
} else {
|
||||
ets_install_putc2(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
USBCDC::operator bool() const {
|
||||
if (itf >= MAX_USB_CDC_DEVICES) {
|
||||
return false;
|
||||
}
|
||||
return connected;
|
||||
}
|
||||
|
||||
#if !ARDUINO_USB_MODE && ARDUINO_USB_CDC_ON_BOOT // Native USB CDC selected
|
||||
// USBSerial is always available to be used
|
||||
USBCDC USBSerial(0);
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_TINYUSB_CDC_ENABLED */
|
||||
#endif /* SOC_USB_OTG_SUPPORTED */
|
||||
144
arduino/USBCDC.h
144
arduino/USBCDC.h
|
|
@ -1,144 +0,0 @@
|
|||
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// 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.
|
||||
#pragma once
|
||||
|
||||
#include "soc/soc_caps.h"
|
||||
#if SOC_USB_OTG_SUPPORTED
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#if CONFIG_TINYUSB_CDC_ENABLED
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "esp_event.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "Stream.h"
|
||||
|
||||
ESP_EVENT_DECLARE_BASE(ARDUINO_USB_CDC_EVENTS);
|
||||
|
||||
typedef enum {
|
||||
ARDUINO_USB_CDC_ANY_EVENT = ESP_EVENT_ANY_ID,
|
||||
ARDUINO_USB_CDC_CONNECTED_EVENT = 0,
|
||||
ARDUINO_USB_CDC_DISCONNECTED_EVENT,
|
||||
ARDUINO_USB_CDC_LINE_STATE_EVENT,
|
||||
ARDUINO_USB_CDC_LINE_CODING_EVENT,
|
||||
ARDUINO_USB_CDC_RX_EVENT,
|
||||
ARDUINO_USB_CDC_TX_EVENT,
|
||||
ARDUINO_USB_CDC_RX_OVERFLOW_EVENT,
|
||||
ARDUINO_USB_CDC_MAX_EVENT,
|
||||
} arduino_usb_cdc_event_t;
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
bool dtr;
|
||||
bool rts;
|
||||
} line_state;
|
||||
struct {
|
||||
uint32_t bit_rate;
|
||||
uint8_t stop_bits; ///< 0: 1 stop bit - 1: 1.5 stop bits - 2: 2 stop bits
|
||||
uint8_t parity; ///< 0: None - 1: Odd - 2: Even - 3: Mark - 4: Space
|
||||
uint8_t data_bits; ///< can be 5, 6, 7, 8 or 16
|
||||
} line_coding;
|
||||
struct {
|
||||
size_t len;
|
||||
} rx;
|
||||
struct {
|
||||
size_t dropped_bytes;
|
||||
} rx_overflow;
|
||||
} arduino_usb_cdc_event_data_t;
|
||||
|
||||
class USBCDC : public Stream {
|
||||
public:
|
||||
USBCDC(uint8_t itf = 0);
|
||||
~USBCDC();
|
||||
|
||||
void onEvent(esp_event_handler_t callback);
|
||||
void onEvent(arduino_usb_cdc_event_t event, esp_event_handler_t callback);
|
||||
|
||||
size_t setRxBufferSize(size_t size);
|
||||
void setTxTimeoutMs(uint32_t timeout);
|
||||
void begin(unsigned long baud = 0);
|
||||
void end();
|
||||
|
||||
int available(void);
|
||||
int availableForWrite(void);
|
||||
int peek(void);
|
||||
int read(void);
|
||||
size_t read(uint8_t *buffer, size_t size);
|
||||
size_t write(uint8_t);
|
||||
size_t write(const uint8_t *buffer, size_t size);
|
||||
void flush(void);
|
||||
|
||||
inline size_t read(char *buffer, size_t size) {
|
||||
return read((uint8_t *)buffer, size);
|
||||
}
|
||||
inline size_t write(const char *buffer, size_t size) {
|
||||
return write((uint8_t *)buffer, size);
|
||||
}
|
||||
inline size_t write(const char *s) {
|
||||
return write((uint8_t *)s, strlen(s));
|
||||
}
|
||||
inline size_t write(unsigned long n) {
|
||||
return write((uint8_t)n);
|
||||
}
|
||||
inline size_t write(long n) {
|
||||
return write((uint8_t)n);
|
||||
}
|
||||
inline size_t write(unsigned int n) {
|
||||
return write((uint8_t)n);
|
||||
}
|
||||
inline size_t write(int n) {
|
||||
return write((uint8_t)n);
|
||||
}
|
||||
uint32_t baudRate();
|
||||
void setDebugOutput(bool);
|
||||
operator bool() const;
|
||||
|
||||
void enableReboot(bool enable);
|
||||
bool rebootEnabled(void);
|
||||
|
||||
//internal methods
|
||||
void _onDFU(void);
|
||||
void _onLineState(bool _dtr, bool _rts);
|
||||
void _onLineCoding(uint32_t _bit_rate, uint8_t _stop_bits, uint8_t _parity, uint8_t _data_bits);
|
||||
void _onRX(void);
|
||||
void _onTX(void);
|
||||
void _onUnplugged(void);
|
||||
|
||||
protected:
|
||||
uint8_t itf;
|
||||
uint32_t bit_rate;
|
||||
uint8_t stop_bits; ///< 0: 1 stop bit - 1: 1.5 stop bits - 2: 2 stop bits
|
||||
uint8_t parity; ///< 0: None - 1: Odd - 2: Even - 3: Mark - 4: Space
|
||||
uint8_t data_bits; ///< can be 5, 6, 7, 8 or 16
|
||||
bool dtr;
|
||||
bool rts;
|
||||
bool connected;
|
||||
bool reboot_enable;
|
||||
QueueHandle_t rx_queue;
|
||||
SemaphoreHandle_t tx_lock;
|
||||
uint32_t tx_timeout_ms;
|
||||
};
|
||||
|
||||
#if !ARDUINO_USB_MODE && ARDUINO_USB_CDC_ON_BOOT // Native USB CDC selected
|
||||
#ifndef USB_SERIAL_IS_DEFINED
|
||||
#define USB_SERIAL_IS_DEFINED 1
|
||||
#endif
|
||||
// USBSerial is always available to be used
|
||||
extern USBCDC USBSerial;
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_TINYUSB_CDC_ENABLED */
|
||||
#endif /* SOC_USB_OTG_SUPPORTED */
|
||||
|
|
@ -1,93 +0,0 @@
|
|||
/*
|
||||
* Udp.cpp: Library to send/receive UDP packets.
|
||||
*
|
||||
* NOTE: UDP is fast, but has some important limitations (thanks to Warren Gray for mentioning these)
|
||||
* 1) UDP does not guarantee the order in which assembled UDP packets are received. This
|
||||
* might not happen often in practice, but in larger network topologies, a UDP
|
||||
* packet can be received out of sequence.
|
||||
* 2) UDP does not guard against lost packets - so packets *can* disappear without the sender being
|
||||
* aware of it. Again, this may not be a concern in practice on small local networks.
|
||||
* For more information, see http://www.cafeaulait.org/course/week12/35.html
|
||||
*
|
||||
* MIT License:
|
||||
* Copyright (c) 2008 Bjoern Hartmann
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* bjoern@cs.stanford.edu 12/30/2008
|
||||
*/
|
||||
|
||||
#ifndef udp_h
|
||||
#define udp_h
|
||||
|
||||
#include "Stream.h"
|
||||
#include "IPAddress.h"
|
||||
|
||||
class UDP: public Stream
|
||||
{
|
||||
|
||||
public:
|
||||
virtual uint8_t begin(uint16_t) =0; // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use
|
||||
virtual uint8_t beginMulticast(IPAddress, uint16_t) { return 0; } // initialize, start listening on specified multicast IP address and port. Returns 1 if successful, 0 on failure
|
||||
virtual void stop() =0; // Finish with the UDP socket
|
||||
|
||||
// Sending UDP packets
|
||||
|
||||
// Start building up a packet to send to the remote host specific in ip and port
|
||||
// Returns 1 if successful, 0 if there was a problem with the supplied IP address or port
|
||||
virtual int beginPacket(IPAddress ip, uint16_t port) =0;
|
||||
// Start building up a packet to send to the remote host specific in host and port
|
||||
// Returns 1 if successful, 0 if there was a problem resolving the hostname or port
|
||||
virtual int beginPacket(const char *host, uint16_t port) =0;
|
||||
// Finish off this packet and send it
|
||||
// Returns 1 if the packet was sent successfully, 0 if there was an error
|
||||
virtual int endPacket() =0;
|
||||
// Write a single byte into the packet
|
||||
virtual size_t write(uint8_t) =0;
|
||||
// Write size bytes from buffer into the packet
|
||||
virtual size_t write(const uint8_t *buffer, size_t size) =0;
|
||||
|
||||
// Start processing the next available incoming packet
|
||||
// Returns the size of the packet in bytes, or 0 if no packets are available
|
||||
virtual int parsePacket() =0;
|
||||
// Number of bytes remaining in the current packet
|
||||
virtual int available() =0;
|
||||
// Read a single byte from the current packet
|
||||
virtual int read() =0;
|
||||
// Read up to len bytes from the current packet and place them into buffer
|
||||
// Returns the number of bytes read, or 0 if none are available
|
||||
virtual int read(unsigned char* buffer, size_t len) =0;
|
||||
// Read up to len characters from the current packet and place them into buffer
|
||||
// Returns the number of characters read, or 0 if none are available
|
||||
virtual int read(char* buffer, size_t len) =0;
|
||||
// Return the next byte from the current packet without moving on to the next byte
|
||||
virtual int peek() =0;
|
||||
virtual void flush() =0; // Finish reading the current packet
|
||||
|
||||
// Return the IP address of the host who sent the current incoming packet
|
||||
virtual IPAddress remoteIP() =0;
|
||||
// Return the port of the host who sent the current incoming packet
|
||||
virtual uint16_t remotePort() =0;
|
||||
protected:
|
||||
uint8_t* rawIPAddress(IPAddress& addr)
|
||||
{
|
||||
return addr.raw_address();
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -1,154 +0,0 @@
|
|||
/*
|
||||
WCharacter.h - Character utility functions for Wiring & Arduino
|
||||
Copyright (c) 2010 Hernando Barragan. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef Character_h
|
||||
#define Character_h
|
||||
|
||||
#include <ctype.h>
|
||||
#define isascii(__c) ((unsigned)(__c)<=0177)
|
||||
#define toascii(__c) ((__c)&0177)
|
||||
|
||||
// WCharacter.h prototypes
|
||||
inline boolean isAlphaNumeric(int c) __attribute__((always_inline));
|
||||
inline boolean isAlpha(int c) __attribute__((always_inline));
|
||||
inline boolean isAscii(int c) __attribute__((always_inline));
|
||||
inline boolean isWhitespace(int c) __attribute__((always_inline));
|
||||
inline boolean isControl(int c) __attribute__((always_inline));
|
||||
inline boolean isDigit(int c) __attribute__((always_inline));
|
||||
inline boolean isGraph(int c) __attribute__((always_inline));
|
||||
inline boolean isLowerCase(int c) __attribute__((always_inline));
|
||||
inline boolean isPrintable(int c) __attribute__((always_inline));
|
||||
inline boolean isPunct(int c) __attribute__((always_inline));
|
||||
inline boolean isSpace(int c) __attribute__((always_inline));
|
||||
inline boolean isUpperCase(int c) __attribute__((always_inline));
|
||||
inline boolean isHexadecimalDigit(int c) __attribute__((always_inline));
|
||||
inline int toAscii(int c) __attribute__((always_inline));
|
||||
inline int toLowerCase(int c) __attribute__((always_inline));
|
||||
inline int toUpperCase(int c) __attribute__((always_inline));
|
||||
|
||||
// Checks for an alphanumeric character.
|
||||
// It is equivalent to (isalpha(c) || isdigit(c)).
|
||||
inline boolean isAlphaNumeric(int c)
|
||||
{
|
||||
return (isalnum(c) == 0 ? false : true);
|
||||
}
|
||||
|
||||
// Checks for an alphabetic character.
|
||||
// It is equivalent to (isupper(c) || islower(c)).
|
||||
inline boolean isAlpha(int c)
|
||||
{
|
||||
return (isalpha(c) == 0 ? false : true);
|
||||
}
|
||||
|
||||
// Checks whether c is a 7-bit unsigned char value
|
||||
// that fits into the ASCII character set.
|
||||
inline boolean isAscii(int c)
|
||||
{
|
||||
return ( isascii (c) == 0 ? false : true);
|
||||
}
|
||||
|
||||
// Checks for a blank character, that is, a space or a tab.
|
||||
inline boolean isWhitespace(int c)
|
||||
{
|
||||
return (isblank(c) == 0 ? false : true);
|
||||
}
|
||||
|
||||
// Checks for a control character.
|
||||
inline boolean isControl(int c)
|
||||
{
|
||||
return (iscntrl(c) == 0 ? false : true);
|
||||
}
|
||||
|
||||
// Checks for a digit (0 through 9).
|
||||
inline boolean isDigit(int c)
|
||||
{
|
||||
return (isdigit(c) == 0 ? false : true);
|
||||
}
|
||||
|
||||
// Checks for any printable character except space.
|
||||
inline boolean isGraph(int c)
|
||||
{
|
||||
return (isgraph(c) == 0 ? false : true);
|
||||
}
|
||||
|
||||
// Checks for a lower-case character.
|
||||
inline boolean isLowerCase(int c)
|
||||
{
|
||||
return (islower(c) == 0 ? false : true);
|
||||
}
|
||||
|
||||
// Checks for any printable character including space.
|
||||
inline boolean isPrintable(int c)
|
||||
{
|
||||
return (isprint(c) == 0 ? false : true);
|
||||
}
|
||||
|
||||
// Checks for any printable character which is not a space
|
||||
// or an alphanumeric character.
|
||||
inline boolean isPunct(int c)
|
||||
{
|
||||
return (ispunct(c) == 0 ? false : true);
|
||||
}
|
||||
|
||||
// Checks for white-space characters. For the avr-libc library,
|
||||
// these are: space, formfeed ('\f'), newline ('\n'), carriage
|
||||
// return ('\r'), horizontal tab ('\t'), and vertical tab ('\v').
|
||||
inline boolean isSpace(int c)
|
||||
{
|
||||
return (isspace(c) == 0 ? false : true);
|
||||
}
|
||||
|
||||
// Checks for an uppercase letter.
|
||||
inline boolean isUpperCase(int c)
|
||||
{
|
||||
return (isupper(c) == 0 ? false : true);
|
||||
}
|
||||
|
||||
// Checks for a hexadecimal digits, i.e. one of 0 1 2 3 4 5 6 7
|
||||
// 8 9 a b c d e f A B C D E F.
|
||||
inline boolean isHexadecimalDigit(int c)
|
||||
{
|
||||
return (isxdigit(c) == 0 ? false : true);
|
||||
}
|
||||
|
||||
// Converts c to a 7-bit unsigned char value that fits into the
|
||||
// ASCII character set, by clearing the high-order bits.
|
||||
inline int toAscii(int c)
|
||||
{
|
||||
return toascii(c);
|
||||
}
|
||||
|
||||
// Warning:
|
||||
// Many people will be unhappy if you use this function.
|
||||
// This function will convert accented letters into random
|
||||
// characters.
|
||||
|
||||
// Converts the letter c to lower case, if possible.
|
||||
inline int toLowerCase(int c)
|
||||
{
|
||||
return tolower(c);
|
||||
}
|
||||
|
||||
// Converts the letter c to upper case, if possible.
|
||||
inline int toUpperCase(int c)
|
||||
{
|
||||
return toupper(c);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -1,860 +0,0 @@
|
|||
/*
|
||||
WString.cpp - String library for Wiring & Arduino
|
||||
...mostly rewritten by Paul Stoffregen...
|
||||
Copyright (c) 2009-10 Hernando Barragan. All rights reserved.
|
||||
Copyright 2011, Paul Stoffregen, paul@pjrc.com
|
||||
Modified by Ivan Grokhotkov, 2014 - esp8266 support
|
||||
Modified by Michael C. Miller, 2015 - esp8266 progmem support
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "WString.h"
|
||||
#include "stdlib_noniso.h"
|
||||
|
||||
/*********************************************/
|
||||
/* Constructors */
|
||||
/*********************************************/
|
||||
|
||||
String::String(const char *cstr) {
|
||||
init();
|
||||
if (cstr)
|
||||
copy(cstr, strlen(cstr));
|
||||
}
|
||||
|
||||
String::String(const char *cstr, unsigned int length) {
|
||||
init();
|
||||
if (cstr)
|
||||
copy(cstr, length);
|
||||
}
|
||||
|
||||
String::String(const String &value) {
|
||||
init();
|
||||
*this = value;
|
||||
}
|
||||
|
||||
String::String(const __FlashStringHelper *pstr) {
|
||||
init();
|
||||
*this = pstr; // see operator =
|
||||
}
|
||||
|
||||
#ifdef __GXX_EXPERIMENTAL_CXX0X__
|
||||
String::String(String &&rval) {
|
||||
init();
|
||||
move(rval);
|
||||
}
|
||||
|
||||
String::String(StringSumHelper &&rval) {
|
||||
init();
|
||||
move(rval);
|
||||
}
|
||||
#endif
|
||||
|
||||
String::String(char c) {
|
||||
init();
|
||||
char buf[] = { c, '\0' };
|
||||
*this = buf;
|
||||
}
|
||||
|
||||
String::String(unsigned char value, unsigned char base) {
|
||||
init();
|
||||
char buf[1 + 8 * sizeof(unsigned char)];
|
||||
utoa(value, buf, base);
|
||||
*this = buf;
|
||||
}
|
||||
|
||||
String::String(int value, unsigned char base) {
|
||||
init();
|
||||
char buf[2 + 8 * sizeof(int)];
|
||||
if (base == 10) {
|
||||
sprintf(buf, "%d", value);
|
||||
} else {
|
||||
itoa(value, buf, base);
|
||||
}
|
||||
*this = buf;
|
||||
}
|
||||
|
||||
String::String(unsigned int value, unsigned char base) {
|
||||
init();
|
||||
char buf[1 + 8 * sizeof(unsigned int)];
|
||||
utoa(value, buf, base);
|
||||
*this = buf;
|
||||
}
|
||||
|
||||
String::String(long value, unsigned char base) {
|
||||
init();
|
||||
char buf[2 + 8 * sizeof(long)];
|
||||
if (base==10) {
|
||||
sprintf(buf, "%ld", value);
|
||||
} else {
|
||||
ltoa(value, buf, base);
|
||||
}
|
||||
*this = buf;
|
||||
}
|
||||
|
||||
String::String(unsigned long value, unsigned char base) {
|
||||
init();
|
||||
char buf[1 + 8 * sizeof(unsigned long)];
|
||||
ultoa(value, buf, base);
|
||||
*this = buf;
|
||||
}
|
||||
|
||||
String::String(float value, unsigned char decimalPlaces) {
|
||||
init();
|
||||
char buf[33];
|
||||
*this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf);
|
||||
}
|
||||
|
||||
String::String(double value, unsigned char decimalPlaces) {
|
||||
init();
|
||||
char buf[33];
|
||||
*this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf);
|
||||
}
|
||||
|
||||
String::~String() {
|
||||
invalidate();
|
||||
}
|
||||
|
||||
// /*********************************************/
|
||||
// /* Memory Management */
|
||||
// /*********************************************/
|
||||
|
||||
inline void String::init(void) {
|
||||
setSSO(false);
|
||||
setBuffer(nullptr);
|
||||
setCapacity(0);
|
||||
setLen(0);
|
||||
}
|
||||
|
||||
void String::invalidate(void) {
|
||||
if(!isSSO() && wbuffer())
|
||||
free(wbuffer());
|
||||
init();
|
||||
}
|
||||
|
||||
unsigned char String::reserve(unsigned int size) {
|
||||
if(buffer() && capacity() >= size)
|
||||
return 1;
|
||||
if(changeBuffer(size)) {
|
||||
if(len() == 0)
|
||||
wbuffer()[0] = 0;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned char String::changeBuffer(unsigned int maxStrLen) {
|
||||
// Can we use SSO here to avoid allocation?
|
||||
if (maxStrLen < sizeof(sso.buff) - 1) {
|
||||
if (isSSO() || !buffer()) {
|
||||
// Already using SSO, nothing to do
|
||||
uint16_t oldLen = len();
|
||||
setSSO(true);
|
||||
setLen(oldLen);
|
||||
return 1;
|
||||
} else { // if bufptr && !isSSO()
|
||||
// Using bufptr, need to shrink into sso.buff
|
||||
char temp[sizeof(sso.buff)];
|
||||
memcpy(temp, buffer(), maxStrLen);
|
||||
free(wbuffer());
|
||||
uint16_t oldLen = len();
|
||||
setSSO(true);
|
||||
memcpy(wbuffer(), temp, maxStrLen);
|
||||
setLen(oldLen);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
// Fallthrough to normal allocator
|
||||
size_t newSize = (maxStrLen + 16) & (~0xf);
|
||||
// Make sure we can fit newsize in the buffer
|
||||
if (newSize > CAPACITY_MAX) {
|
||||
return false;
|
||||
}
|
||||
uint16_t oldLen = len();
|
||||
char *newbuffer = (char *) realloc(isSSO() ? nullptr : wbuffer(), newSize);
|
||||
if (newbuffer) {
|
||||
size_t oldSize = capacity() + 1; // include NULL.
|
||||
if (isSSO()) {
|
||||
// Copy the SSO buffer into allocated space
|
||||
memmove(newbuffer, sso.buff, sizeof(sso.buff));
|
||||
}
|
||||
if (newSize > oldSize)
|
||||
{
|
||||
memset(newbuffer + oldSize, 0, newSize - oldSize);
|
||||
}
|
||||
setSSO(false);
|
||||
setCapacity(newSize - 1);
|
||||
setBuffer(newbuffer);
|
||||
setLen(oldLen); // Needed in case of SSO where len() never existed
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// /*********************************************/
|
||||
// /* Copy and Move */
|
||||
// /*********************************************/
|
||||
|
||||
String & String::copy(const char *cstr, unsigned int length) {
|
||||
if(!reserve(length)) {
|
||||
invalidate();
|
||||
return *this;
|
||||
}
|
||||
memmove(wbuffer(), cstr, length + 1);
|
||||
setLen(length);
|
||||
return *this;
|
||||
}
|
||||
|
||||
String & String::copy(const __FlashStringHelper *pstr, unsigned int length) {
|
||||
if (!reserve(length)) {
|
||||
invalidate();
|
||||
return *this;
|
||||
}
|
||||
memcpy_P(wbuffer(), (PGM_P)pstr, length + 1); // We know wbuffer() cannot ever be in PROGMEM, so memcpy safe here
|
||||
setLen(length);
|
||||
return *this;
|
||||
}
|
||||
|
||||
#ifdef __GXX_EXPERIMENTAL_CXX0X__
|
||||
void String::move(String &rhs) {
|
||||
if(buffer()) {
|
||||
if(capacity() >= rhs.len()) {
|
||||
memmove(wbuffer(), rhs.buffer(), rhs.length() + 1);
|
||||
setLen(rhs.len());
|
||||
rhs.invalidate();
|
||||
return;
|
||||
} else {
|
||||
if (!isSSO()) {
|
||||
free(wbuffer());
|
||||
setBuffer(nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rhs.isSSO()) {
|
||||
setSSO(true);
|
||||
memmove(sso.buff, rhs.sso.buff, sizeof(sso.buff));
|
||||
} else {
|
||||
setSSO(false);
|
||||
setBuffer(rhs.wbuffer());
|
||||
}
|
||||
setCapacity(rhs.capacity());
|
||||
setLen(rhs.len());
|
||||
rhs.setSSO(false);
|
||||
rhs.setCapacity(0);
|
||||
rhs.setBuffer(nullptr);
|
||||
rhs.setLen(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
String & String::operator =(const String &rhs) {
|
||||
if(this == &rhs)
|
||||
return *this;
|
||||
|
||||
if(rhs.buffer())
|
||||
copy(rhs.buffer(), rhs.len());
|
||||
else
|
||||
invalidate();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
#ifdef __GXX_EXPERIMENTAL_CXX0X__
|
||||
String & String::operator =(String &&rval) {
|
||||
if(this != &rval)
|
||||
move(rval);
|
||||
return *this;
|
||||
}
|
||||
|
||||
String & String::operator =(StringSumHelper &&rval) {
|
||||
if(this != &rval)
|
||||
move(rval);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
String & String::operator =(const char *cstr) {
|
||||
if(cstr)
|
||||
copy(cstr, strlen(cstr));
|
||||
else
|
||||
invalidate();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
String & String::operator =(const __FlashStringHelper *pstr) {
|
||||
if(pstr)
|
||||
copy(pstr, strlen_P((PGM_P)pstr));
|
||||
else
|
||||
invalidate();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// /*********************************************/
|
||||
// /* concat */
|
||||
// /*********************************************/
|
||||
|
||||
unsigned char String::concat(const String &s) {
|
||||
// Special case if we're concatting ourself (s += s;) since we may end up
|
||||
// realloc'ing the buffer and moving s.buffer in the method called
|
||||
if (&s == this) {
|
||||
unsigned int newlen = 2 * len();
|
||||
if (!s.buffer())
|
||||
return 0;
|
||||
if (s.len() == 0)
|
||||
return 1;
|
||||
if (!reserve(newlen))
|
||||
return 0;
|
||||
memmove(wbuffer() + len(), buffer(), len());
|
||||
setLen(newlen);
|
||||
wbuffer()[len()] = 0;
|
||||
return 1;
|
||||
} else {
|
||||
return concat(s.buffer(), s.len());
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char String::concat(const char *cstr, unsigned int length) {
|
||||
unsigned int newlen = len() + length;
|
||||
if(!cstr)
|
||||
return 0;
|
||||
if(length == 0)
|
||||
return 1;
|
||||
if(!reserve(newlen))
|
||||
return 0;
|
||||
if (cstr >= wbuffer() && cstr < wbuffer() + len())
|
||||
// compatible with SSO in ram #6155 (case "x += x.c_str()")
|
||||
memmove(wbuffer() + len(), cstr, length + 1);
|
||||
else
|
||||
// compatible with source in flash #6367
|
||||
memcpy_P(wbuffer() + len(), cstr, length + 1);
|
||||
setLen(newlen);
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned char String::concat(const char *cstr) {
|
||||
if(!cstr)
|
||||
return 0;
|
||||
return concat(cstr, strlen(cstr));
|
||||
}
|
||||
|
||||
unsigned char String::concat(char c) {
|
||||
char buf[] = { c, '\0' };
|
||||
return concat(buf, 1);
|
||||
}
|
||||
|
||||
unsigned char String::concat(unsigned char num) {
|
||||
char buf[1 + 3 * sizeof(unsigned char)];
|
||||
return concat(buf, sprintf(buf, "%d", num));
|
||||
}
|
||||
|
||||
unsigned char String::concat(int num) {
|
||||
char buf[2 + 3 * sizeof(int)];
|
||||
return concat(buf, sprintf(buf, "%d", num));
|
||||
}
|
||||
|
||||
unsigned char String::concat(unsigned int num) {
|
||||
char buf[1 + 3 * sizeof(unsigned int)];
|
||||
utoa(num, buf, 10);
|
||||
return concat(buf, strlen(buf));
|
||||
}
|
||||
|
||||
unsigned char String::concat(long num) {
|
||||
char buf[2 + 3 * sizeof(long)];
|
||||
return concat(buf, sprintf(buf, "%ld", num));
|
||||
}
|
||||
|
||||
unsigned char String::concat(unsigned long num) {
|
||||
char buf[1 + 3 * sizeof(unsigned long)];
|
||||
ultoa(num, buf, 10);
|
||||
return concat(buf, strlen(buf));
|
||||
}
|
||||
|
||||
unsigned char String::concat(float num) {
|
||||
char buf[20];
|
||||
char* string = dtostrf(num, 4, 2, buf);
|
||||
return concat(string, strlen(string));
|
||||
}
|
||||
|
||||
unsigned char String::concat(double num) {
|
||||
char buf[20];
|
||||
char* string = dtostrf(num, 4, 2, buf);
|
||||
return concat(string, strlen(string));
|
||||
}
|
||||
|
||||
unsigned char String::concat(const __FlashStringHelper * str) {
|
||||
if (!str) return 0;
|
||||
int length = strlen_P((PGM_P)str);
|
||||
if (length == 0) return 1;
|
||||
unsigned int newlen = len() + length;
|
||||
if (!reserve(newlen)) return 0;
|
||||
memcpy_P(wbuffer() + len(), (PGM_P)str, length + 1);
|
||||
setLen(newlen);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*********************************************/
|
||||
/* Concatenate */
|
||||
/*********************************************/
|
||||
|
||||
StringSumHelper & operator +(const StringSumHelper &lhs, const String &rhs) {
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if(!a.concat(rhs.buffer(), rhs.len()))
|
||||
a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
StringSumHelper & operator +(const StringSumHelper &lhs, const char *cstr) {
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if(!cstr || !a.concat(cstr, strlen(cstr)))
|
||||
a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
StringSumHelper & operator +(const StringSumHelper &lhs, char c) {
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if(!a.concat(c))
|
||||
a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
StringSumHelper & operator +(const StringSumHelper &lhs, unsigned char num) {
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if(!a.concat(num))
|
||||
a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
StringSumHelper & operator +(const StringSumHelper &lhs, int num) {
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if(!a.concat(num))
|
||||
a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
StringSumHelper & operator +(const StringSumHelper &lhs, unsigned int num) {
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if(!a.concat(num))
|
||||
a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
StringSumHelper & operator +(const StringSumHelper &lhs, long num) {
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if(!a.concat(num))
|
||||
a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
StringSumHelper & operator +(const StringSumHelper &lhs, unsigned long num) {
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if(!a.concat(num))
|
||||
a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
StringSumHelper & operator +(const StringSumHelper &lhs, float num) {
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if(!a.concat(num))
|
||||
a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
StringSumHelper & operator +(const StringSumHelper &lhs, double num) {
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if(!a.concat(num))
|
||||
a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *rhs)
|
||||
{
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if (!a.concat(rhs))
|
||||
a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
// /*********************************************/
|
||||
// /* Comparison */
|
||||
// /*********************************************/
|
||||
|
||||
int String::compareTo(const String &s) const {
|
||||
if(!buffer() || !s.buffer()) {
|
||||
if(s.buffer() && s.len() > 0)
|
||||
return 0 - *(unsigned char *) s.buffer();
|
||||
if(buffer() && len() > 0)
|
||||
return *(unsigned char *) buffer();
|
||||
return 0;
|
||||
}
|
||||
return strcmp(buffer(), s.buffer());
|
||||
}
|
||||
|
||||
unsigned char String::equals(const String &s2) const {
|
||||
return (len() == s2.len() && compareTo(s2) == 0);
|
||||
}
|
||||
|
||||
unsigned char String::equals(const char *cstr) const {
|
||||
if(len() == 0)
|
||||
return (cstr == NULL || *cstr == 0);
|
||||
if(cstr == NULL)
|
||||
return buffer()[0] == 0;
|
||||
return strcmp(buffer(), cstr) == 0;
|
||||
}
|
||||
|
||||
unsigned char String::operator<(const String &rhs) const {
|
||||
return compareTo(rhs) < 0;
|
||||
}
|
||||
|
||||
unsigned char String::operator>(const String &rhs) const {
|
||||
return compareTo(rhs) > 0;
|
||||
}
|
||||
|
||||
unsigned char String::operator<=(const String &rhs) const {
|
||||
return compareTo(rhs) <= 0;
|
||||
}
|
||||
|
||||
unsigned char String::operator>=(const String &rhs) const {
|
||||
return compareTo(rhs) >= 0;
|
||||
}
|
||||
|
||||
unsigned char String::equalsIgnoreCase(const String &s2) const {
|
||||
if(this == &s2)
|
||||
return 1;
|
||||
if(len() != s2.len())
|
||||
return 0;
|
||||
if(len() == 0)
|
||||
return 1;
|
||||
const char *p1 = buffer();
|
||||
const char *p2 = s2.buffer();
|
||||
while(*p1) {
|
||||
if(tolower(*p1++) != tolower(*p2++))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned char String::equalsConstantTime(const String &s2) const {
|
||||
// To avoid possible time-based attacks present function
|
||||
// compares given strings in a constant time.
|
||||
if(len() != s2.len())
|
||||
return 0;
|
||||
//at this point lengths are the same
|
||||
if(len() == 0)
|
||||
return 1;
|
||||
//at this point lengths are the same and non-zero
|
||||
const char *p1 = buffer();
|
||||
const char *p2 = s2.buffer();
|
||||
unsigned int equalchars = 0;
|
||||
unsigned int diffchars = 0;
|
||||
while(*p1) {
|
||||
if(*p1 == *p2)
|
||||
++equalchars;
|
||||
else
|
||||
++diffchars;
|
||||
++p1;
|
||||
++p2;
|
||||
}
|
||||
//the following should force a constant time eval of the condition without a compiler "logical shortcut"
|
||||
unsigned char equalcond = (equalchars == len());
|
||||
unsigned char diffcond = (diffchars == 0);
|
||||
return (equalcond & diffcond); //bitwise AND
|
||||
}
|
||||
|
||||
unsigned char String::startsWith(const String &s2) const {
|
||||
if(len() < s2.len())
|
||||
return 0;
|
||||
return startsWith(s2, 0);
|
||||
}
|
||||
|
||||
unsigned char String::startsWith(const String &s2, unsigned int offset) const {
|
||||
if(offset > (unsigned)(len() - s2.len()) || !buffer() || !s2.buffer())
|
||||
return 0;
|
||||
return strncmp(&buffer()[offset], s2.buffer(), s2.len()) == 0;
|
||||
}
|
||||
|
||||
unsigned char String::endsWith(const String &s2) const {
|
||||
if(len() < s2.len() || !buffer() || !s2.buffer())
|
||||
return 0;
|
||||
return strcmp(&buffer()[len() - s2.len()], s2.buffer()) == 0;
|
||||
}
|
||||
|
||||
// /*********************************************/
|
||||
// /* Character Access */
|
||||
// /*********************************************/
|
||||
|
||||
char String::charAt(unsigned int loc) const {
|
||||
return operator[](loc);
|
||||
}
|
||||
|
||||
void String::setCharAt(unsigned int loc, char c) {
|
||||
if(loc < len())
|
||||
wbuffer()[loc] = c;
|
||||
}
|
||||
|
||||
char & String::operator[](unsigned int index) {
|
||||
static char dummy_writable_char;
|
||||
if(index >= len() || !buffer()) {
|
||||
dummy_writable_char = 0;
|
||||
return dummy_writable_char;
|
||||
}
|
||||
return wbuffer()[index];
|
||||
}
|
||||
|
||||
char String::operator[](unsigned int index) const {
|
||||
if(index >= len() || !buffer())
|
||||
return 0;
|
||||
return buffer()[index];
|
||||
}
|
||||
|
||||
void String::getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index) const {
|
||||
if(!bufsize || !buf)
|
||||
return;
|
||||
if(index >= len()) {
|
||||
buf[0] = 0;
|
||||
return;
|
||||
}
|
||||
unsigned int n = bufsize - 1;
|
||||
if(n > len() - index)
|
||||
n = len() - index;
|
||||
strncpy((char *) buf, buffer() + index, n);
|
||||
buf[n] = 0;
|
||||
}
|
||||
|
||||
// /*********************************************/
|
||||
// /* Search */
|
||||
// /*********************************************/
|
||||
|
||||
int String::indexOf(char c) const {
|
||||
return indexOf(c, 0);
|
||||
}
|
||||
|
||||
int String::indexOf(char ch, unsigned int fromIndex) const {
|
||||
if(fromIndex >= len())
|
||||
return -1;
|
||||
const char* temp = strchr(buffer() + fromIndex, ch);
|
||||
if(temp == NULL)
|
||||
return -1;
|
||||
return temp - buffer();
|
||||
}
|
||||
|
||||
int String::indexOf(const String &s2) const {
|
||||
return indexOf(s2, 0);
|
||||
}
|
||||
|
||||
int String::indexOf(const String &s2, unsigned int fromIndex) const {
|
||||
if(fromIndex >= len())
|
||||
return -1;
|
||||
const char *found = strstr(buffer() + fromIndex, s2.buffer());
|
||||
if(found == NULL)
|
||||
return -1;
|
||||
return found - buffer();
|
||||
}
|
||||
|
||||
int String::lastIndexOf(char theChar) const {
|
||||
return lastIndexOf(theChar, len() - 1);
|
||||
}
|
||||
|
||||
int String::lastIndexOf(char ch, unsigned int fromIndex) const {
|
||||
if(fromIndex >= len())
|
||||
return -1;
|
||||
char tempchar = buffer()[fromIndex + 1];
|
||||
wbuffer()[fromIndex + 1] = '\0';
|
||||
char* temp = strrchr(wbuffer(), ch);
|
||||
wbuffer()[fromIndex + 1] = tempchar;
|
||||
if(temp == NULL)
|
||||
return -1;
|
||||
return temp - buffer();
|
||||
}
|
||||
|
||||
int String::lastIndexOf(const String &s2) const {
|
||||
return lastIndexOf(s2, len() - s2.len());
|
||||
}
|
||||
|
||||
int String::lastIndexOf(const String &s2, unsigned int fromIndex) const {
|
||||
if(s2.len() == 0 || len() == 0 || s2.len() > len())
|
||||
return -1;
|
||||
if(fromIndex >= len())
|
||||
fromIndex = len() - 1;
|
||||
int found = -1;
|
||||
for(char *p = wbuffer(); p <= wbuffer() + fromIndex; p++) {
|
||||
p = strstr(p, s2.buffer());
|
||||
if(!p)
|
||||
break;
|
||||
if((unsigned int) (p - wbuffer()) <= fromIndex)
|
||||
found = p - buffer();
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
String String::substring(unsigned int left, unsigned int right) const {
|
||||
if(left > right) {
|
||||
unsigned int temp = right;
|
||||
right = left;
|
||||
left = temp;
|
||||
}
|
||||
String out;
|
||||
if(left >= len())
|
||||
return out;
|
||||
if(right > len())
|
||||
right = len();
|
||||
out.copy(buffer() + left, right - left);
|
||||
return out;
|
||||
}
|
||||
|
||||
// /*********************************************/
|
||||
// /* Modification */
|
||||
// /*********************************************/
|
||||
|
||||
void String::replace(char find, char replace) {
|
||||
if(!buffer())
|
||||
return;
|
||||
for(char *p = wbuffer(); *p; p++) {
|
||||
if(*p == find)
|
||||
*p = replace;
|
||||
}
|
||||
}
|
||||
|
||||
void String::replace(const String& find, const String& replace) {
|
||||
if(len() == 0 || find.len() == 0)
|
||||
return;
|
||||
int diff = replace.len() - find.len();
|
||||
char *readFrom = wbuffer();
|
||||
char *foundAt;
|
||||
if(diff == 0) {
|
||||
while((foundAt = strstr(readFrom, find.buffer())) != NULL) {
|
||||
memmove(foundAt, replace.buffer(), replace.len());
|
||||
readFrom = foundAt + replace.len();
|
||||
}
|
||||
} else if(diff < 0) {
|
||||
char *writeTo = wbuffer();
|
||||
unsigned int l = len();
|
||||
while((foundAt = strstr(readFrom, find.buffer())) != NULL) {
|
||||
unsigned int n = foundAt - readFrom;
|
||||
memmove(writeTo, readFrom, n);
|
||||
writeTo += n;
|
||||
memmove(writeTo, replace.buffer(), replace.len());
|
||||
writeTo += replace.len();
|
||||
readFrom = foundAt + find.len();
|
||||
l += diff;
|
||||
}
|
||||
memmove(writeTo, readFrom, strlen(readFrom)+1);
|
||||
setLen(l);
|
||||
} else {
|
||||
unsigned int size = len(); // compute size needed for result
|
||||
while((foundAt = strstr(readFrom, find.buffer())) != NULL) {
|
||||
readFrom = foundAt + find.len();
|
||||
size += diff;
|
||||
}
|
||||
if(size == len())
|
||||
return;
|
||||
if(size > capacity() && !changeBuffer(size))
|
||||
return; // XXX: tell user!
|
||||
int index = len() - 1;
|
||||
while(index >= 0 && (index = lastIndexOf(find, index)) >= 0) {
|
||||
readFrom = wbuffer() + index + find.len();
|
||||
memmove(readFrom + diff, readFrom, len() - (readFrom - buffer()));
|
||||
int newLen = len() + diff;
|
||||
memmove(wbuffer() + index, replace.buffer(), replace.len());
|
||||
setLen(newLen);
|
||||
wbuffer()[newLen] = 0;
|
||||
index--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void String::remove(unsigned int index) {
|
||||
// Pass the biggest integer as the count. The remove method
|
||||
// below will take care of truncating it at the end of the
|
||||
// string.
|
||||
remove(index, (unsigned int) -1);
|
||||
}
|
||||
|
||||
void String::remove(unsigned int index, unsigned int count) {
|
||||
if(index >= len()) {
|
||||
return;
|
||||
}
|
||||
if(count <= 0) {
|
||||
return;
|
||||
}
|
||||
if(count > len() - index) {
|
||||
count = len() - index;
|
||||
}
|
||||
char *writeTo = wbuffer() + index;
|
||||
unsigned int newlen = len() - count;
|
||||
memmove(writeTo, wbuffer() + index + count, newlen - index);
|
||||
setLen(newlen);
|
||||
wbuffer()[newlen] = 0;
|
||||
}
|
||||
|
||||
void String::toLowerCase(void) {
|
||||
if(!buffer())
|
||||
return;
|
||||
for(char *p = wbuffer(); *p; p++) {
|
||||
*p = tolower(*p);
|
||||
}
|
||||
}
|
||||
|
||||
void String::toUpperCase(void) {
|
||||
if(!buffer())
|
||||
return;
|
||||
for(char *p = wbuffer(); *p; p++) {
|
||||
*p = toupper(*p);
|
||||
}
|
||||
}
|
||||
|
||||
void String::trim(void) {
|
||||
if(!buffer() || len() == 0)
|
||||
return;
|
||||
char *begin = wbuffer();
|
||||
while(isspace(*begin))
|
||||
begin++;
|
||||
char *end = wbuffer() + len() - 1;
|
||||
while(isspace(*end) && end >= begin)
|
||||
end--;
|
||||
unsigned int newlen = end + 1 - begin;
|
||||
if(begin > buffer())
|
||||
memmove(wbuffer(), begin, newlen);
|
||||
setLen(newlen);
|
||||
wbuffer()[newlen] = 0;
|
||||
}
|
||||
|
||||
// /*********************************************/
|
||||
// /* Parsing / Conversion */
|
||||
// /*********************************************/
|
||||
|
||||
long String::toInt(void) const {
|
||||
if (buffer())
|
||||
return atol(buffer());
|
||||
return 0;
|
||||
}
|
||||
|
||||
float String::toFloat(void) const {
|
||||
if (buffer())
|
||||
return atof(buffer());
|
||||
return 0;
|
||||
}
|
||||
|
||||
double String::toDouble(void) const
|
||||
{
|
||||
if (buffer())
|
||||
return atof(buffer());
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
// global empty string to allow returning const String& with nothing
|
||||
|
||||
const String emptyString;
|
||||
|
|
@ -1,381 +0,0 @@
|
|||
/*
|
||||
WString.h - String library for Wiring & Arduino
|
||||
...mostly rewritten by Paul Stoffregen...
|
||||
Copyright (c) 2009-10 Hernando Barragan. All right reserved.
|
||||
Copyright 2011, Paul Stoffregen, paul@pjrc.com
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef String_class_h
|
||||
#define String_class_h
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "pgmspace.h"
|
||||
#include <stdint.h>
|
||||
|
||||
// An inherited class for holding the result of a concatenation. These
|
||||
// result objects are assumed to be writable by subsequent concatenations.
|
||||
class StringSumHelper;
|
||||
|
||||
// an abstract class used as a means to proide a unique pointer type
|
||||
// but really has no body
|
||||
class __FlashStringHelper;
|
||||
#define FPSTR(pstr_pointer) (reinterpret_cast<const __FlashStringHelper *>(pstr_pointer))
|
||||
#define F(string_literal) (FPSTR(PSTR(string_literal)))
|
||||
|
||||
// The string class
|
||||
class String {
|
||||
// use a function pointer to allow for "if (s)" without the
|
||||
// complications of an operator bool(). for more information, see:
|
||||
// http://www.artima.com/cppsource/safebool.html
|
||||
typedef void (String::*StringIfHelperType)() const;
|
||||
void StringIfHelper() const {
|
||||
}
|
||||
|
||||
public:
|
||||
// constructors
|
||||
// creates a copy of the initial value.
|
||||
// if the initial value is null or invalid, or if memory allocation
|
||||
// fails, the string will be marked as invalid (i.e. "if (s)" will
|
||||
// be false).
|
||||
String(const char *cstr = "");
|
||||
String(const char *cstr, unsigned int length);
|
||||
#ifdef __GXX_EXPERIMENTAL_CXX0X__
|
||||
String(const uint8_t *cstr, unsigned int length) : String((const char*)cstr, length) {}
|
||||
#endif
|
||||
String(const String &str);
|
||||
String(const __FlashStringHelper *str);
|
||||
#ifdef __GXX_EXPERIMENTAL_CXX0X__
|
||||
String(String &&rval);
|
||||
String(StringSumHelper &&rval);
|
||||
#endif
|
||||
explicit String(char c);
|
||||
explicit String(unsigned char, unsigned char base = 10);
|
||||
explicit String(int, unsigned char base = 10);
|
||||
explicit String(unsigned int, unsigned char base = 10);
|
||||
explicit String(long, unsigned char base = 10);
|
||||
explicit String(unsigned long, unsigned char base = 10);
|
||||
explicit String(float, unsigned char decimalPlaces = 2);
|
||||
explicit String(double, unsigned char decimalPlaces = 2);
|
||||
~String(void);
|
||||
|
||||
// memory management
|
||||
// return true on success, false on failure (in which case, the string
|
||||
// is left unchanged). reserve(0), if successful, will validate an
|
||||
// invalid string (i.e., "if (s)" will be true afterwards)
|
||||
unsigned char reserve(unsigned int size);
|
||||
inline unsigned int length(void) const {
|
||||
if(buffer()) {
|
||||
return len();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
inline void clear(void) {
|
||||
setLen(0);
|
||||
}
|
||||
inline bool isEmpty(void) const {
|
||||
return length() == 0;
|
||||
}
|
||||
|
||||
// creates a copy of the assigned value. if the value is null or
|
||||
// invalid, or if the memory allocation fails, the string will be
|
||||
// marked as invalid ("if (s)" will be false).
|
||||
String & operator =(const String &rhs);
|
||||
String & operator =(const char *cstr);
|
||||
String & operator = (const __FlashStringHelper *str);
|
||||
#ifdef __GXX_EXPERIMENTAL_CXX0X__
|
||||
String & operator =(String &&rval);
|
||||
String & operator =(StringSumHelper &&rval);
|
||||
#endif
|
||||
|
||||
// concatenate (works w/ built-in types)
|
||||
|
||||
// returns true on success, false on failure (in which case, the string
|
||||
// is left unchanged). if the argument is null or invalid, the
|
||||
// concatenation is considered unsuccessful.
|
||||
unsigned char concat(const String &str);
|
||||
unsigned char concat(const char *cstr);
|
||||
unsigned char concat(const char *cstr, unsigned int length);
|
||||
unsigned char concat(const uint8_t *cstr, unsigned int length) {return concat((const char*)cstr, length);}
|
||||
unsigned char concat(char c);
|
||||
unsigned char concat(unsigned char c);
|
||||
unsigned char concat(int num);
|
||||
unsigned char concat(unsigned int num);
|
||||
unsigned char concat(long num);
|
||||
unsigned char concat(unsigned long num);
|
||||
unsigned char concat(float num);
|
||||
unsigned char concat(double num);
|
||||
unsigned char concat(const __FlashStringHelper * str);
|
||||
|
||||
// if there's not enough memory for the concatenated value, the string
|
||||
// will be left unchanged (but this isn't signalled in any way)
|
||||
String & operator +=(const String &rhs) {
|
||||
concat(rhs);
|
||||
return (*this);
|
||||
}
|
||||
String & operator +=(const char *cstr) {
|
||||
concat(cstr);
|
||||
return (*this);
|
||||
}
|
||||
String & operator +=(char c) {
|
||||
concat(c);
|
||||
return (*this);
|
||||
}
|
||||
String & operator +=(unsigned char num) {
|
||||
concat(num);
|
||||
return (*this);
|
||||
}
|
||||
String & operator +=(int num) {
|
||||
concat(num);
|
||||
return (*this);
|
||||
}
|
||||
String & operator +=(unsigned int num) {
|
||||
concat(num);
|
||||
return (*this);
|
||||
}
|
||||
String & operator +=(long num) {
|
||||
concat(num);
|
||||
return (*this);
|
||||
}
|
||||
String & operator +=(unsigned long num) {
|
||||
concat(num);
|
||||
return (*this);
|
||||
}
|
||||
String & operator +=(float num) {
|
||||
concat(num);
|
||||
return (*this);
|
||||
}
|
||||
String & operator +=(double num) {
|
||||
concat(num);
|
||||
return (*this);
|
||||
}
|
||||
String & operator += (const __FlashStringHelper *str){
|
||||
concat(str);
|
||||
return (*this);
|
||||
}
|
||||
|
||||
friend StringSumHelper & operator +(const StringSumHelper &lhs, const String &rhs);
|
||||
friend StringSumHelper & operator +(const StringSumHelper &lhs, const char *cstr);
|
||||
friend StringSumHelper & operator +(const StringSumHelper &lhs, char c);
|
||||
friend StringSumHelper & operator +(const StringSumHelper &lhs, unsigned char num);
|
||||
friend StringSumHelper & operator +(const StringSumHelper &lhs, int num);
|
||||
friend StringSumHelper & operator +(const StringSumHelper &lhs, unsigned int num);
|
||||
friend StringSumHelper & operator +(const StringSumHelper &lhs, long num);
|
||||
friend StringSumHelper & operator +(const StringSumHelper &lhs, unsigned long num);
|
||||
friend StringSumHelper & operator +(const StringSumHelper &lhs, float num);
|
||||
friend StringSumHelper & operator +(const StringSumHelper &lhs, double num);
|
||||
friend StringSumHelper & operator +(const StringSumHelper &lhs, const __FlashStringHelper *rhs);
|
||||
|
||||
// comparison (only works w/ Strings and "strings")
|
||||
operator StringIfHelperType() const {
|
||||
return buffer() ? &String::StringIfHelper : 0;
|
||||
}
|
||||
int compareTo(const String &s) const;
|
||||
unsigned char equals(const String &s) const;
|
||||
unsigned char equals(const char *cstr) const;
|
||||
unsigned char operator ==(const String &rhs) const {
|
||||
return equals(rhs);
|
||||
}
|
||||
unsigned char operator ==(const char *cstr) const {
|
||||
return equals(cstr);
|
||||
}
|
||||
unsigned char operator !=(const String &rhs) const {
|
||||
return !equals(rhs);
|
||||
}
|
||||
unsigned char operator !=(const char *cstr) const {
|
||||
return !equals(cstr);
|
||||
}
|
||||
unsigned char operator <(const String &rhs) const;
|
||||
unsigned char operator >(const String &rhs) const;
|
||||
unsigned char operator <=(const String &rhs) const;
|
||||
unsigned char operator >=(const String &rhs) const;
|
||||
unsigned char equalsIgnoreCase(const String &s) const;
|
||||
unsigned char equalsConstantTime(const String &s) const;
|
||||
unsigned char startsWith(const String &prefix) const;
|
||||
unsigned char startsWith(const char *prefix) const {
|
||||
return this->startsWith(String(prefix));
|
||||
}
|
||||
unsigned char startsWith(const __FlashStringHelper *prefix) const {
|
||||
return this->startsWith(String(prefix));
|
||||
}
|
||||
unsigned char startsWith(const String &prefix, unsigned int offset) const;
|
||||
unsigned char endsWith(const String &suffix) const;
|
||||
unsigned char endsWith(const char *suffix) const {
|
||||
return this->endsWith(String(suffix));
|
||||
}
|
||||
unsigned char endsWith(const __FlashStringHelper * suffix) const {
|
||||
return this->endsWith(String(suffix));
|
||||
}
|
||||
|
||||
// character access
|
||||
char charAt(unsigned int index) const;
|
||||
void setCharAt(unsigned int index, char c);
|
||||
char operator [](unsigned int index) const;
|
||||
char& operator [](unsigned int index);
|
||||
void getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index = 0) const;
|
||||
void toCharArray(char *buf, unsigned int bufsize, unsigned int index = 0) const {
|
||||
getBytes((unsigned char *) buf, bufsize, index);
|
||||
}
|
||||
const char* c_str() const { return buffer(); }
|
||||
char* begin() { return wbuffer(); }
|
||||
char* end() { return wbuffer() + length(); }
|
||||
const char* begin() const { return c_str(); }
|
||||
const char* end() const { return c_str() + length(); }
|
||||
|
||||
// search
|
||||
int indexOf(char ch) const;
|
||||
int indexOf(char ch, unsigned int fromIndex) const;
|
||||
int indexOf(const String &str) const;
|
||||
int indexOf(const String &str, unsigned int fromIndex) const;
|
||||
int lastIndexOf(char ch) const;
|
||||
int lastIndexOf(char ch, unsigned int fromIndex) const;
|
||||
int lastIndexOf(const String &str) const;
|
||||
int lastIndexOf(const String &str, unsigned int fromIndex) const;
|
||||
String substring(unsigned int beginIndex) const {
|
||||
return substring(beginIndex, len());
|
||||
}
|
||||
;
|
||||
String substring(unsigned int beginIndex, unsigned int endIndex) const;
|
||||
|
||||
// modification
|
||||
void replace(char find, char replace);
|
||||
void replace(const String &find, const String &replace);
|
||||
void replace(const char *find, const String &replace) {
|
||||
this->replace(String(find), replace);
|
||||
}
|
||||
void replace(const __FlashStringHelper *find, const String &replace) {
|
||||
this->replace(String(find), replace);
|
||||
}
|
||||
void replace(const char *find, const char *replace) {
|
||||
this->replace(String(find), String(replace));
|
||||
}
|
||||
void replace(const __FlashStringHelper *find, const char *replace) {
|
||||
this->replace(String(find), String(replace));
|
||||
}
|
||||
void replace(const __FlashStringHelper *find, const __FlashStringHelper *replace) {
|
||||
this->replace(String(find), String(replace));
|
||||
}
|
||||
void remove(unsigned int index);
|
||||
void remove(unsigned int index, unsigned int count);
|
||||
void toLowerCase(void);
|
||||
void toUpperCase(void);
|
||||
void trim(void);
|
||||
|
||||
// parsing/conversion
|
||||
long toInt(void) const;
|
||||
float toFloat(void) const;
|
||||
double toDouble(void) const;
|
||||
|
||||
protected:
|
||||
// Contains the string info when we're not in SSO mode
|
||||
struct _ptr {
|
||||
char * buff;
|
||||
uint32_t cap;
|
||||
uint32_t len;
|
||||
};
|
||||
// This allows strings up up to 11 (10 + \0 termination) without any extra space.
|
||||
enum { SSOSIZE = sizeof(struct _ptr) + 4 - 1 }; // Characters to allocate space for SSO, must be 12 or more
|
||||
struct _sso {
|
||||
char buff[SSOSIZE];
|
||||
unsigned char len : 7; // Ensure only one byte is allocated by GCC for the bitfields
|
||||
unsigned char isSSO : 1;
|
||||
} __attribute__((packed)); // Ensure that GCC doesn't expand the flag byte to a 32-bit word for alignment issues
|
||||
#ifdef BOARD_HAS_PSRAM
|
||||
enum { CAPACITY_MAX = 3145728 };
|
||||
#else
|
||||
enum { CAPACITY_MAX = 65535 };
|
||||
#endif
|
||||
union {
|
||||
struct _ptr ptr;
|
||||
struct _sso sso;
|
||||
};
|
||||
// Accessor functions
|
||||
inline bool isSSO() const { return sso.isSSO; }
|
||||
inline unsigned int len() const { return isSSO() ? sso.len : ptr.len; }
|
||||
inline unsigned int capacity() const { return isSSO() ? (unsigned int)SSOSIZE - 1 : ptr.cap; } // Size of max string not including terminal NUL
|
||||
inline void setSSO(bool set) { sso.isSSO = set; }
|
||||
inline void setLen(int len) {
|
||||
if (isSSO()) {
|
||||
sso.len = len;
|
||||
sso.buff[len] = 0;
|
||||
} else {
|
||||
ptr.len = len;
|
||||
if (ptr.buff) {
|
||||
ptr.buff[len] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
inline void setCapacity(int cap) { if (!isSSO()) ptr.cap = cap; }
|
||||
inline void setBuffer(char *buff) { if (!isSSO()) ptr.buff = buff; }
|
||||
// Buffer accessor functions
|
||||
inline const char *buffer() const { return (const char *)(isSSO() ? sso.buff : ptr.buff); }
|
||||
inline char *wbuffer() const { return isSSO() ? const_cast<char *>(sso.buff) : ptr.buff; } // Writable version of buffer
|
||||
|
||||
protected:
|
||||
void init(void);
|
||||
void invalidate(void);
|
||||
unsigned char changeBuffer(unsigned int maxStrLen);
|
||||
|
||||
// copy and move
|
||||
String & copy(const char *cstr, unsigned int length);
|
||||
String & copy(const __FlashStringHelper *pstr, unsigned int length);
|
||||
#ifdef __GXX_EXPERIMENTAL_CXX0X__
|
||||
void move(String &rhs);
|
||||
#endif
|
||||
};
|
||||
|
||||
class StringSumHelper: public String {
|
||||
public:
|
||||
StringSumHelper(const String &s) :
|
||||
String(s) {
|
||||
}
|
||||
StringSumHelper(const char *p) :
|
||||
String(p) {
|
||||
}
|
||||
StringSumHelper(char c) :
|
||||
String(c) {
|
||||
}
|
||||
StringSumHelper(unsigned char num) :
|
||||
String(num) {
|
||||
}
|
||||
StringSumHelper(int num) :
|
||||
String(num) {
|
||||
}
|
||||
StringSumHelper(unsigned int num) :
|
||||
String(num) {
|
||||
}
|
||||
StringSumHelper(long num) :
|
||||
String(num) {
|
||||
}
|
||||
StringSumHelper(unsigned long num) :
|
||||
String(num) {
|
||||
}
|
||||
StringSumHelper(float num) :
|
||||
String(num) {
|
||||
}
|
||||
StringSumHelper(double num) :
|
||||
String(num) {
|
||||
}
|
||||
};
|
||||
|
||||
extern const String emptyString;
|
||||
|
||||
#endif // __cplusplus
|
||||
#endif // String_class_h
|
||||
551
arduino/Wire.cpp
551
arduino/Wire.cpp
|
|
@ -1,551 +0,0 @@
|
|||
/*
|
||||
TwoWire.cpp - TWI/I2C library for Arduino & Wiring
|
||||
Copyright (c) 2006 Nicholas Zambetti. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Modified 2012 by Todd Krein (todd@krein.org) to implement repeated starts
|
||||
Modified December 2014 by Ivan Grokhotkov (ivan@esp8266.com) - esp8266 support
|
||||
Modified April 2015 by Hrsto Gochkov (ficeto@ficeto.com) - alternative esp8266 support
|
||||
Modified Nov 2017 by Chuck Todd (ctodd@cableone.net) - ESP32 ISR Support
|
||||
Modified Nov 2021 by Hristo Gochkov <Me-No-Dev> to support ESP-IDF API
|
||||
*/
|
||||
|
||||
extern "C" {
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
}
|
||||
|
||||
#include "esp32-hal-i2c.h"
|
||||
#include "esp32-hal-i2c-slave.h"
|
||||
#include "Wire.h"
|
||||
#include "Arduino.h"
|
||||
|
||||
TwoWire::TwoWire(uint8_t bus_num)
|
||||
:num(bus_num & 1)
|
||||
,sda(-1)
|
||||
,scl(-1)
|
||||
,rxIndex(0)
|
||||
,rxLength(0)
|
||||
,txLength(0)
|
||||
,txAddress(0)
|
||||
,_timeOutMillis(50)
|
||||
,nonStop(false)
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
,nonStopTask(NULL)
|
||||
,lock(NULL)
|
||||
#endif
|
||||
,is_slave(false)
|
||||
,user_onRequest(NULL)
|
||||
,user_onReceive(NULL)
|
||||
{}
|
||||
|
||||
TwoWire::~TwoWire()
|
||||
{
|
||||
end();
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
if(lock != NULL){
|
||||
vSemaphoreDelete(lock);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool TwoWire::initPins(int sdaPin, int sclPin)
|
||||
{
|
||||
if(sdaPin < 0) { // default param passed
|
||||
if(num == 0) {
|
||||
if(sda==-1) {
|
||||
sdaPin = SDA; //use Default Pin
|
||||
} else {
|
||||
sdaPin = sda; // reuse prior pin
|
||||
}
|
||||
} else {
|
||||
if(sda==-1) {
|
||||
log_e("no Default SDA Pin for Second Peripheral");
|
||||
return false; //no Default pin for Second Peripheral
|
||||
} else {
|
||||
sdaPin = sda; // reuse prior pin
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(sclPin < 0) { // default param passed
|
||||
if(num == 0) {
|
||||
if(scl == -1) {
|
||||
sclPin = SCL; // use Default pin
|
||||
} else {
|
||||
sclPin = scl; // reuse prior pin
|
||||
}
|
||||
} else {
|
||||
if(scl == -1) {
|
||||
log_e("no Default SCL Pin for Second Peripheral");
|
||||
return false; //no Default pin for Second Peripheral
|
||||
} else {
|
||||
sclPin = scl; // reuse prior pin
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sda = sdaPin;
|
||||
scl = sclPin;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TwoWire::setPins(int sdaPin, int sclPin)
|
||||
{
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
if(lock == NULL){
|
||||
lock = xSemaphoreCreateMutex();
|
||||
if(lock == NULL){
|
||||
log_e("xSemaphoreCreateMutex failed");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
//acquire lock
|
||||
if(xSemaphoreTake(lock, portMAX_DELAY) != pdTRUE){
|
||||
log_e("could not acquire lock");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
if(!i2cIsInit(num)){
|
||||
initPins(sdaPin, sclPin);
|
||||
} else {
|
||||
log_e("bus already initialized. change pins only when not.");
|
||||
}
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
//release lock
|
||||
xSemaphoreGive(lock);
|
||||
#endif
|
||||
return !i2cIsInit(num);
|
||||
}
|
||||
|
||||
// Slave Begin
|
||||
bool TwoWire::begin(uint8_t addr, int sdaPin, int sclPin, uint32_t frequency)
|
||||
{
|
||||
bool started = false;
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
if(lock == NULL){
|
||||
lock = xSemaphoreCreateMutex();
|
||||
if(lock == NULL){
|
||||
log_e("xSemaphoreCreateMutex failed");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
//acquire lock
|
||||
if(xSemaphoreTake(lock, portMAX_DELAY) != pdTRUE){
|
||||
log_e("could not acquire lock");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
if(is_slave){
|
||||
log_w("Bus already started in Slave Mode.");
|
||||
started = true;
|
||||
goto end;
|
||||
}
|
||||
if(i2cIsInit(num)){
|
||||
log_e("Bus already started in Master Mode.");
|
||||
goto end;
|
||||
}
|
||||
if(!initPins(sdaPin, sclPin)){
|
||||
goto end;
|
||||
}
|
||||
i2cSlaveAttachCallbacks(num, onRequestService, onReceiveService, this);
|
||||
if(i2cSlaveInit(num, sda, scl, addr, frequency, I2C_BUFFER_LENGTH, I2C_BUFFER_LENGTH) != ESP_OK){
|
||||
log_e("Slave Init ERROR");
|
||||
goto end;
|
||||
}
|
||||
is_slave = true;
|
||||
started = true;
|
||||
end:
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
//release lock
|
||||
xSemaphoreGive(lock);
|
||||
#endif
|
||||
return started;
|
||||
}
|
||||
|
||||
// Master Begin
|
||||
bool TwoWire::begin(int sdaPin, int sclPin, uint32_t frequency)
|
||||
{
|
||||
bool started = false;
|
||||
esp_err_t err = ESP_OK;
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
if(lock == NULL){
|
||||
lock = xSemaphoreCreateMutex();
|
||||
if(lock == NULL){
|
||||
log_e("xSemaphoreCreateMutex failed");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
//acquire lock
|
||||
if(xSemaphoreTake(lock, portMAX_DELAY) != pdTRUE){
|
||||
log_e("could not acquire lock");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
if(is_slave){
|
||||
log_e("Bus already started in Slave Mode.");
|
||||
goto end;
|
||||
}
|
||||
if(i2cIsInit(num)){
|
||||
log_w("Bus already started in Master Mode.");
|
||||
started = true;
|
||||
goto end;
|
||||
}
|
||||
if(!initPins(sdaPin, sclPin)){
|
||||
goto end;
|
||||
}
|
||||
err = i2cInit(num, sda, scl, frequency);
|
||||
started = (err == ESP_OK);
|
||||
|
||||
end:
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
//release lock
|
||||
xSemaphoreGive(lock);
|
||||
#endif
|
||||
return started;
|
||||
|
||||
}
|
||||
|
||||
bool TwoWire::end()
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
if(lock != NULL){
|
||||
//acquire lock
|
||||
if(xSemaphoreTake(lock, portMAX_DELAY) != pdTRUE){
|
||||
log_e("could not acquire lock");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
if(is_slave){
|
||||
err = i2cSlaveDeinit(num);
|
||||
if(err == ESP_OK){
|
||||
is_slave = false;
|
||||
}
|
||||
} else if(i2cIsInit(num)){
|
||||
err = i2cDeinit(num);
|
||||
}
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
//release lock
|
||||
xSemaphoreGive(lock);
|
||||
}
|
||||
#endif
|
||||
return (err == ESP_OK);
|
||||
}
|
||||
|
||||
uint32_t TwoWire::getClock()
|
||||
{
|
||||
uint32_t frequency = 0;
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
//acquire lock
|
||||
if(lock == NULL || xSemaphoreTake(lock, portMAX_DELAY) != pdTRUE){
|
||||
log_e("could not acquire lock");
|
||||
} else {
|
||||
#endif
|
||||
if(is_slave){
|
||||
log_e("Bus is in Slave Mode");
|
||||
} else {
|
||||
i2cGetClock(num, &frequency);
|
||||
}
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
//release lock
|
||||
xSemaphoreGive(lock);
|
||||
}
|
||||
#endif
|
||||
return frequency;
|
||||
}
|
||||
|
||||
bool TwoWire::setClock(uint32_t frequency)
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
//acquire lock
|
||||
if(lock == NULL || xSemaphoreTake(lock, portMAX_DELAY) != pdTRUE){
|
||||
log_e("could not acquire lock");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
if(is_slave){
|
||||
log_e("Bus is in Slave Mode");
|
||||
err = ESP_FAIL;
|
||||
} else {
|
||||
err = i2cSetClock(num, frequency);
|
||||
}
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
//release lock
|
||||
xSemaphoreGive(lock);
|
||||
#endif
|
||||
return (err == ESP_OK);
|
||||
}
|
||||
|
||||
void TwoWire::setTimeOut(uint16_t timeOutMillis)
|
||||
{
|
||||
_timeOutMillis = timeOutMillis;
|
||||
}
|
||||
|
||||
uint16_t TwoWire::getTimeOut()
|
||||
{
|
||||
return _timeOutMillis;
|
||||
}
|
||||
|
||||
void TwoWire::beginTransmission(uint16_t address)
|
||||
{
|
||||
if(is_slave){
|
||||
log_e("Bus is in Slave Mode");
|
||||
return;
|
||||
}
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
if(nonStop && nonStopTask == xTaskGetCurrentTaskHandle()){
|
||||
log_e("Unfinished Repeated Start transaction! Expected requestFrom, not beginTransmission! Clearing...");
|
||||
//release lock
|
||||
xSemaphoreGive(lock);
|
||||
}
|
||||
//acquire lock
|
||||
if(lock == NULL || xSemaphoreTake(lock, portMAX_DELAY) != pdTRUE){
|
||||
log_e("could not acquire lock");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
nonStop = false;
|
||||
txAddress = address;
|
||||
txLength = 0;
|
||||
}
|
||||
|
||||
uint8_t TwoWire::endTransmission(bool sendStop)
|
||||
{
|
||||
if(is_slave){
|
||||
log_e("Bus is in Slave Mode");
|
||||
return 4;
|
||||
}
|
||||
esp_err_t err = ESP_OK;
|
||||
if(sendStop){
|
||||
err = i2cWrite(num, txAddress, txBuffer, txLength, _timeOutMillis);
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
//release lock
|
||||
xSemaphoreGive(lock);
|
||||
#endif
|
||||
} else {
|
||||
//mark as non-stop
|
||||
nonStop = true;
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
nonStopTask = xTaskGetCurrentTaskHandle();
|
||||
#endif
|
||||
}
|
||||
switch(err){
|
||||
case ESP_OK: return 0;
|
||||
case ESP_FAIL: return 2;
|
||||
case ESP_ERR_TIMEOUT: return 5;
|
||||
default: break;
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
|
||||
size_t TwoWire::requestFrom(uint16_t address, size_t size, bool sendStop)
|
||||
{
|
||||
if(is_slave){
|
||||
log_e("Bus is in Slave Mode");
|
||||
return 0;
|
||||
}
|
||||
esp_err_t err = ESP_OK;
|
||||
if(nonStop
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
&& nonStopTask == xTaskGetCurrentTaskHandle()
|
||||
#endif
|
||||
){
|
||||
if(address != txAddress){
|
||||
log_e("Unfinished Repeated Start transaction! Expected address do not match! %u != %u", address, txAddress);
|
||||
return 0;
|
||||
}
|
||||
nonStop = false;
|
||||
rxIndex = 0;
|
||||
rxLength = 0;
|
||||
err = i2cWriteReadNonStop(num, address, txBuffer, txLength, rxBuffer, size, _timeOutMillis, &rxLength);
|
||||
} else {
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
//acquire lock
|
||||
if(lock == NULL || xSemaphoreTake(lock, portMAX_DELAY) != pdTRUE){
|
||||
log_e("could not acquire lock");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
rxIndex = 0;
|
||||
rxLength = 0;
|
||||
err = i2cRead(num, address, rxBuffer, size, _timeOutMillis, &rxLength);
|
||||
}
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
//release lock
|
||||
xSemaphoreGive(lock);
|
||||
#endif
|
||||
return rxLength;
|
||||
}
|
||||
|
||||
size_t TwoWire::write(uint8_t data)
|
||||
{
|
||||
if(txLength >= I2C_BUFFER_LENGTH) {
|
||||
return 0;
|
||||
}
|
||||
txBuffer[txLength++] = data;
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t TwoWire::write(const uint8_t *data, size_t quantity)
|
||||
{
|
||||
for(size_t i = 0; i < quantity; ++i) {
|
||||
if(!write(data[i])) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return quantity;
|
||||
|
||||
}
|
||||
|
||||
int TwoWire::available(void)
|
||||
{
|
||||
int result = rxLength - rxIndex;
|
||||
return result;
|
||||
}
|
||||
|
||||
int TwoWire::read(void)
|
||||
{
|
||||
int value = -1;
|
||||
if(rxIndex < rxLength) {
|
||||
value = rxBuffer[rxIndex++];
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
int TwoWire::peek(void)
|
||||
{
|
||||
int value = -1;
|
||||
if(rxIndex < rxLength) {
|
||||
value = rxBuffer[rxIndex];
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
void TwoWire::flush(void)
|
||||
{
|
||||
rxIndex = 0;
|
||||
rxLength = 0;
|
||||
txLength = 0;
|
||||
//i2cFlush(num); // cleanup
|
||||
}
|
||||
|
||||
size_t TwoWire::requestFrom(uint8_t address, size_t len, bool sendStop)
|
||||
{
|
||||
return requestFrom(static_cast<uint16_t>(address), static_cast<size_t>(len), static_cast<bool>(sendStop));
|
||||
}
|
||||
|
||||
uint8_t TwoWire::requestFrom(uint8_t address, uint8_t len, uint8_t sendStop)
|
||||
{
|
||||
return requestFrom(static_cast<uint16_t>(address), static_cast<size_t>(len), static_cast<bool>(sendStop));
|
||||
}
|
||||
|
||||
uint8_t TwoWire::requestFrom(uint16_t address, uint8_t len, uint8_t sendStop)
|
||||
{
|
||||
return requestFrom(address, static_cast<size_t>(len), static_cast<bool>(sendStop));
|
||||
}
|
||||
|
||||
/* Added to match the Arduino function definition: https://github.com/arduino/ArduinoCore-API/blob/173e8eadced2ad32eeb93bcbd5c49f8d6a055ea6/api/HardwareI2C.h#L39
|
||||
* See: https://github.com/arduino-libraries/ArduinoECCX08/issues/25
|
||||
*/
|
||||
uint8_t TwoWire::requestFrom(uint16_t address, uint8_t len, bool stopBit)
|
||||
{
|
||||
return requestFrom((uint16_t)address, (size_t)len, stopBit);
|
||||
}
|
||||
|
||||
uint8_t TwoWire::requestFrom(uint8_t address, uint8_t len)
|
||||
{
|
||||
return requestFrom(static_cast<uint16_t>(address), static_cast<size_t>(len), true);
|
||||
}
|
||||
|
||||
uint8_t TwoWire::requestFrom(uint16_t address, uint8_t len)
|
||||
{
|
||||
return requestFrom(address, static_cast<size_t>(len), true);
|
||||
}
|
||||
|
||||
uint8_t TwoWire::requestFrom(int address, int len)
|
||||
{
|
||||
return requestFrom(static_cast<uint16_t>(address), static_cast<size_t>(len), true);
|
||||
}
|
||||
|
||||
uint8_t TwoWire::requestFrom(int address, int len, int sendStop)
|
||||
{
|
||||
return static_cast<uint8_t>(requestFrom(static_cast<uint16_t>(address), static_cast<size_t>(len), static_cast<bool>(sendStop)));
|
||||
}
|
||||
|
||||
void TwoWire::beginTransmission(int address)
|
||||
{
|
||||
beginTransmission(static_cast<uint16_t>(address));
|
||||
}
|
||||
|
||||
void TwoWire::beginTransmission(uint8_t address)
|
||||
{
|
||||
beginTransmission(static_cast<uint16_t>(address));
|
||||
}
|
||||
|
||||
uint8_t TwoWire::endTransmission(void)
|
||||
{
|
||||
return endTransmission(true);
|
||||
}
|
||||
|
||||
size_t TwoWire::slaveWrite(const uint8_t * buffer, size_t len)
|
||||
{
|
||||
return i2cSlaveWrite(num, buffer, len, _timeOutMillis);
|
||||
}
|
||||
|
||||
void TwoWire::onReceiveService(uint8_t num, uint8_t* inBytes, size_t numBytes, bool stop, void * arg)
|
||||
{
|
||||
TwoWire * wire = (TwoWire*)arg;
|
||||
if(!wire->user_onReceive){
|
||||
return;
|
||||
}
|
||||
for(uint8_t i = 0; i < numBytes; ++i){
|
||||
wire->rxBuffer[i] = inBytes[i];
|
||||
}
|
||||
wire->rxIndex = 0;
|
||||
wire->rxLength = numBytes;
|
||||
wire->user_onReceive(numBytes);
|
||||
}
|
||||
|
||||
void TwoWire::onRequestService(uint8_t num, void * arg)
|
||||
{
|
||||
TwoWire * wire = (TwoWire*)arg;
|
||||
if(!wire->user_onRequest){
|
||||
return;
|
||||
}
|
||||
wire->txLength = 0;
|
||||
wire->user_onRequest();
|
||||
if(wire->txLength){
|
||||
wire->slaveWrite((uint8_t*)wire->txBuffer, wire->txLength);
|
||||
}
|
||||
}
|
||||
|
||||
void TwoWire::onReceive( void (*function)(int) )
|
||||
{
|
||||
user_onReceive = function;
|
||||
}
|
||||
|
||||
// sets function called on slave read
|
||||
void TwoWire::onRequest( void (*function)(void) )
|
||||
{
|
||||
user_onRequest = function;
|
||||
}
|
||||
|
||||
|
||||
TwoWire Wire = TwoWire(0);
|
||||
TwoWire Wire1 = TwoWire(1);
|
||||
142
arduino/Wire.h
142
arduino/Wire.h
|
|
@ -1,142 +0,0 @@
|
|||
/*
|
||||
TwoWire.h - TWI/I2C library for Arduino & Wiring
|
||||
Copyright (c) 2006 Nicholas Zambetti. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Modified 2012 by Todd Krein (todd@krein.org) to implement repeated starts
|
||||
Modified December 2014 by Ivan Grokhotkov (ivan@esp8266.com) - esp8266 support
|
||||
Modified April 2015 by Hrsto Gochkov (ficeto@ficeto.com) - alternative esp8266 support
|
||||
Modified November 2017 by Chuck Todd <stickbreaker on GitHub> to use ISR and increase stability.
|
||||
Modified Nov 2021 by Hristo Gochkov <Me-No-Dev> to support ESP-IDF API
|
||||
*/
|
||||
|
||||
#ifndef TwoWire_h
|
||||
#define TwoWire_h
|
||||
|
||||
#include "esp32-hal.h"
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#endif
|
||||
#include "Stream.h"
|
||||
|
||||
#ifndef I2C_BUFFER_LENGTH
|
||||
#define I2C_BUFFER_LENGTH 128
|
||||
#endif
|
||||
typedef void(*user_onRequest)(void);
|
||||
typedef void(*user_onReceive)(uint8_t*, int);
|
||||
|
||||
class TwoWire: public Stream
|
||||
{
|
||||
protected:
|
||||
uint8_t num;
|
||||
int8_t sda;
|
||||
int8_t scl;
|
||||
|
||||
uint8_t rxBuffer[I2C_BUFFER_LENGTH];
|
||||
size_t rxIndex;
|
||||
size_t rxLength;
|
||||
|
||||
uint8_t txBuffer[I2C_BUFFER_LENGTH];
|
||||
size_t txLength;
|
||||
uint16_t txAddress;
|
||||
|
||||
uint32_t _timeOutMillis;
|
||||
bool nonStop;
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
TaskHandle_t nonStopTask;
|
||||
SemaphoreHandle_t lock;
|
||||
#endif
|
||||
private:
|
||||
bool is_slave;
|
||||
void (*user_onRequest)(void);
|
||||
void (*user_onReceive)(int);
|
||||
static void onRequestService(uint8_t, void *);
|
||||
static void onReceiveService(uint8_t, uint8_t*, size_t, bool, void *);
|
||||
bool initPins(int sdaPin, int sclPin);
|
||||
|
||||
public:
|
||||
TwoWire(uint8_t bus_num);
|
||||
~TwoWire();
|
||||
|
||||
//call setPins() first, so that begin() can be called without arguments from libraries
|
||||
bool setPins(int sda, int scl);
|
||||
|
||||
bool begin(int sda=-1, int scl=-1, uint32_t frequency=0); // returns true, if successful init of i2c bus
|
||||
bool begin(uint8_t slaveAddr, int sda=-1, int scl=-1, uint32_t frequency=0);
|
||||
bool end();
|
||||
|
||||
void setTimeOut(uint16_t timeOutMillis); // default timeout of i2c transactions is 50ms
|
||||
uint16_t getTimeOut();
|
||||
|
||||
bool setClock(uint32_t);
|
||||
uint32_t getClock();
|
||||
|
||||
void beginTransmission(uint16_t address);
|
||||
void beginTransmission(uint8_t address);
|
||||
void beginTransmission(int address);
|
||||
|
||||
uint8_t endTransmission(bool sendStop);
|
||||
uint8_t endTransmission(void);
|
||||
|
||||
size_t requestFrom(uint16_t address, size_t size, bool sendStop);
|
||||
uint8_t requestFrom(uint16_t address, uint8_t size, bool sendStop);
|
||||
uint8_t requestFrom(uint16_t address, uint8_t size, uint8_t sendStop);
|
||||
size_t requestFrom(uint8_t address, size_t len, bool stopBit);
|
||||
uint8_t requestFrom(uint16_t address, uint8_t size);
|
||||
uint8_t requestFrom(uint8_t address, uint8_t size, uint8_t sendStop);
|
||||
uint8_t requestFrom(uint8_t address, uint8_t size);
|
||||
uint8_t requestFrom(int address, int size, int sendStop);
|
||||
uint8_t requestFrom(int address, int size);
|
||||
|
||||
size_t write(uint8_t);
|
||||
size_t write(const uint8_t *, size_t);
|
||||
int available(void);
|
||||
int read(void);
|
||||
int peek(void);
|
||||
void flush(void);
|
||||
|
||||
inline size_t write(const char * s)
|
||||
{
|
||||
return write((uint8_t*) s, strlen(s));
|
||||
}
|
||||
inline size_t write(unsigned long n)
|
||||
{
|
||||
return write((uint8_t)n);
|
||||
}
|
||||
inline size_t write(long n)
|
||||
{
|
||||
return write((uint8_t)n);
|
||||
}
|
||||
inline size_t write(unsigned int n)
|
||||
{
|
||||
return write((uint8_t)n);
|
||||
}
|
||||
inline size_t write(int n)
|
||||
{
|
||||
return write((uint8_t)n);
|
||||
}
|
||||
|
||||
void onReceive( void (*)(int) );
|
||||
void onRequest( void (*)(void) );
|
||||
size_t slaveWrite(const uint8_t *, size_t);
|
||||
};
|
||||
|
||||
extern TwoWire Wire;
|
||||
extern TwoWire Wire1;
|
||||
|
||||
#endif
|
||||
|
|
@ -1,129 +0,0 @@
|
|||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 ERROPiX
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "analogWrite.h"
|
||||
|
||||
analog_write_channel_t _analog_write_channels[16] = {
|
||||
{-1, 5000, 13},
|
||||
{-1, 5000, 13},
|
||||
{-1, 5000, 13},
|
||||
{-1, 5000, 13},
|
||||
{-1, 5000, 13},
|
||||
{-1, 5000, 13},
|
||||
{-1, 5000, 13},
|
||||
{-1, 5000, 13},
|
||||
{-1, 5000, 13},
|
||||
{-1, 5000, 13},
|
||||
{-1, 5000, 13},
|
||||
{-1, 5000, 13},
|
||||
{-1, 5000, 13},
|
||||
{-1, 5000, 13},
|
||||
{-1, 5000, 13},
|
||||
{-1, 5000, 13}};
|
||||
|
||||
int analogWriteChannel(uint8_t pin)
|
||||
{
|
||||
int channel = -1;
|
||||
|
||||
// Check if pin already attached to a channel
|
||||
for (uint8_t i = 0; i < 16; i++)
|
||||
{
|
||||
if (_analog_write_channels[i].pin == pin)
|
||||
{
|
||||
channel = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If not, attach it to a free channel
|
||||
if (channel == -1)
|
||||
{
|
||||
for (uint8_t i = 0; i < 16; i++)
|
||||
{
|
||||
if (_analog_write_channels[i].pin == -1)
|
||||
{
|
||||
_analog_write_channels[i].pin = pin;
|
||||
channel = i;
|
||||
ledcAttachChannel(channel, _analog_write_channels[i].frequency, _analog_write_channels[i].resolution, channel);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return channel;
|
||||
}
|
||||
|
||||
void analogWriteFrequency(double frequency)
|
||||
{
|
||||
for (uint8_t i = 0; i < 16; i++)
|
||||
{
|
||||
_analog_write_channels[i].frequency = frequency;
|
||||
}
|
||||
}
|
||||
|
||||
void analogWriteFrequency(uint8_t pin, double frequency)
|
||||
{
|
||||
int channel = analogWriteChannel(pin);
|
||||
|
||||
// Make sure the pin was attached to a channel, if not do nothing
|
||||
if (channel != -1 && channel < 16)
|
||||
{
|
||||
_analog_write_channels[channel].frequency = frequency;
|
||||
}
|
||||
}
|
||||
|
||||
void analogWriteResolution(uint8_t resolution)
|
||||
{
|
||||
for (uint8_t i = 0; i < 16; i++)
|
||||
{
|
||||
_analog_write_channels[i].resolution = resolution;
|
||||
}
|
||||
}
|
||||
|
||||
void analogWriteResolution(uint8_t pin, uint8_t resolution)
|
||||
{
|
||||
int channel = analogWriteChannel(pin);
|
||||
|
||||
// Make sure the pin was attached to a channel, if not do nothing
|
||||
if (channel != -1 && channel < 16)
|
||||
{
|
||||
_analog_write_channels[channel].resolution = resolution;
|
||||
}
|
||||
}
|
||||
|
||||
void analogWrite(uint8_t pin, uint32_t value, uint32_t valueMax)
|
||||
{
|
||||
int channel = analogWriteChannel(pin);
|
||||
|
||||
// Make sure the pin was attached to a channel, if not do nothing
|
||||
if (channel != -1 && channel < 16)
|
||||
{
|
||||
uint8_t resolution = _analog_write_channels[channel].resolution;
|
||||
uint32_t levels = pow(2, resolution);
|
||||
uint32_t duty = ((levels - 1) / valueMax) * min(value, valueMax);
|
||||
|
||||
// write duty to LEDC
|
||||
ledcWrite(channel, duty);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 ERROPiX
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _ESP32_ANALOG_WRITE_
|
||||
#define _ESP32_ANALOG_WRITE_
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
typedef struct analog_write_channel
|
||||
{
|
||||
int8_t pin;
|
||||
double frequency;
|
||||
uint8_t resolution;
|
||||
} analog_write_channel_t;
|
||||
|
||||
int analogWriteChannel(uint8_t pin);
|
||||
|
||||
void analogWriteFrequency(double frequency);
|
||||
void analogWriteFrequency(uint8_t pin, double frequency);
|
||||
|
||||
void analogWriteResolution(uint8_t resolution);
|
||||
void analogWriteResolution(uint8_t pin, uint8_t resolution);
|
||||
|
||||
void analogWrite(uint8_t pin, uint32_t value, uint32_t valueMax = 255);
|
||||
|
||||
#endif
|
||||
534
arduino/binary.h
534
arduino/binary.h
|
|
@ -1,534 +0,0 @@
|
|||
/*
|
||||
binary.h - Definitions for binary constants
|
||||
Copyright (c) 2006 David A. Mellis. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef Binary_h
|
||||
#define Binary_h
|
||||
|
||||
#define B0 0
|
||||
#define B00 0
|
||||
#define B000 0
|
||||
#define B0000 0
|
||||
#define B00000 0
|
||||
#define B000000 0
|
||||
#define B0000000 0
|
||||
#define B00000000 0
|
||||
#define B1 1
|
||||
#define B01 1
|
||||
#define B001 1
|
||||
#define B0001 1
|
||||
#define B00001 1
|
||||
#define B000001 1
|
||||
#define B0000001 1
|
||||
#define B00000001 1
|
||||
#define B10 2
|
||||
#define B010 2
|
||||
#define B0010 2
|
||||
#define B00010 2
|
||||
#define B000010 2
|
||||
#define B0000010 2
|
||||
#define B00000010 2
|
||||
#define B11 3
|
||||
#define B011 3
|
||||
#define B0011 3
|
||||
#define B00011 3
|
||||
#define B000011 3
|
||||
#define B0000011 3
|
||||
#define B00000011 3
|
||||
#define B100 4
|
||||
#define B0100 4
|
||||
#define B00100 4
|
||||
#define B000100 4
|
||||
#define B0000100 4
|
||||
#define B00000100 4
|
||||
#define B101 5
|
||||
#define B0101 5
|
||||
#define B00101 5
|
||||
#define B000101 5
|
||||
#define B0000101 5
|
||||
#define B00000101 5
|
||||
#define B110 6
|
||||
#define B0110 6
|
||||
#define B00110 6
|
||||
#define B000110 6
|
||||
#define B0000110 6
|
||||
#define B00000110 6
|
||||
#define B111 7
|
||||
#define B0111 7
|
||||
#define B00111 7
|
||||
#define B000111 7
|
||||
#define B0000111 7
|
||||
#define B00000111 7
|
||||
#define B1000 8
|
||||
#define B01000 8
|
||||
#define B001000 8
|
||||
#define B0001000 8
|
||||
#define B00001000 8
|
||||
#define B1001 9
|
||||
#define B01001 9
|
||||
#define B001001 9
|
||||
#define B0001001 9
|
||||
#define B00001001 9
|
||||
#define B1010 10
|
||||
#define B01010 10
|
||||
#define B001010 10
|
||||
#define B0001010 10
|
||||
#define B00001010 10
|
||||
#define B1011 11
|
||||
#define B01011 11
|
||||
#define B001011 11
|
||||
#define B0001011 11
|
||||
#define B00001011 11
|
||||
#define B1100 12
|
||||
#define B01100 12
|
||||
#define B001100 12
|
||||
#define B0001100 12
|
||||
#define B00001100 12
|
||||
#define B1101 13
|
||||
#define B01101 13
|
||||
#define B001101 13
|
||||
#define B0001101 13
|
||||
#define B00001101 13
|
||||
#define B1110 14
|
||||
#define B01110 14
|
||||
#define B001110 14
|
||||
#define B0001110 14
|
||||
#define B00001110 14
|
||||
#define B1111 15
|
||||
#define B01111 15
|
||||
#define B001111 15
|
||||
#define B0001111 15
|
||||
#define B00001111 15
|
||||
#define B10000 16
|
||||
#define B010000 16
|
||||
#define B0010000 16
|
||||
#define B00010000 16
|
||||
#define B10001 17
|
||||
#define B010001 17
|
||||
#define B0010001 17
|
||||
#define B00010001 17
|
||||
#define B10010 18
|
||||
#define B010010 18
|
||||
#define B0010010 18
|
||||
#define B00010010 18
|
||||
#define B10011 19
|
||||
#define B010011 19
|
||||
#define B0010011 19
|
||||
#define B00010011 19
|
||||
#define B10100 20
|
||||
#define B010100 20
|
||||
#define B0010100 20
|
||||
#define B00010100 20
|
||||
#define B10101 21
|
||||
#define B010101 21
|
||||
#define B0010101 21
|
||||
#define B00010101 21
|
||||
#define B10110 22
|
||||
#define B010110 22
|
||||
#define B0010110 22
|
||||
#define B00010110 22
|
||||
#define B10111 23
|
||||
#define B010111 23
|
||||
#define B0010111 23
|
||||
#define B00010111 23
|
||||
#define B11000 24
|
||||
#define B011000 24
|
||||
#define B0011000 24
|
||||
#define B00011000 24
|
||||
#define B11001 25
|
||||
#define B011001 25
|
||||
#define B0011001 25
|
||||
#define B00011001 25
|
||||
#define B11010 26
|
||||
#define B011010 26
|
||||
#define B0011010 26
|
||||
#define B00011010 26
|
||||
#define B11011 27
|
||||
#define B011011 27
|
||||
#define B0011011 27
|
||||
#define B00011011 27
|
||||
#define B11100 28
|
||||
#define B011100 28
|
||||
#define B0011100 28
|
||||
#define B00011100 28
|
||||
#define B11101 29
|
||||
#define B011101 29
|
||||
#define B0011101 29
|
||||
#define B00011101 29
|
||||
#define B11110 30
|
||||
#define B011110 30
|
||||
#define B0011110 30
|
||||
#define B00011110 30
|
||||
#define B11111 31
|
||||
#define B011111 31
|
||||
#define B0011111 31
|
||||
#define B00011111 31
|
||||
#define B100000 32
|
||||
#define B0100000 32
|
||||
#define B00100000 32
|
||||
#define B100001 33
|
||||
#define B0100001 33
|
||||
#define B00100001 33
|
||||
#define B100010 34
|
||||
#define B0100010 34
|
||||
#define B00100010 34
|
||||
#define B100011 35
|
||||
#define B0100011 35
|
||||
#define B00100011 35
|
||||
#define B100100 36
|
||||
#define B0100100 36
|
||||
#define B00100100 36
|
||||
#define B100101 37
|
||||
#define B0100101 37
|
||||
#define B00100101 37
|
||||
#define B100110 38
|
||||
#define B0100110 38
|
||||
#define B00100110 38
|
||||
#define B100111 39
|
||||
#define B0100111 39
|
||||
#define B00100111 39
|
||||
#define B101000 40
|
||||
#define B0101000 40
|
||||
#define B00101000 40
|
||||
#define B101001 41
|
||||
#define B0101001 41
|
||||
#define B00101001 41
|
||||
#define B101010 42
|
||||
#define B0101010 42
|
||||
#define B00101010 42
|
||||
#define B101011 43
|
||||
#define B0101011 43
|
||||
#define B00101011 43
|
||||
#define B101100 44
|
||||
#define B0101100 44
|
||||
#define B00101100 44
|
||||
#define B101101 45
|
||||
#define B0101101 45
|
||||
#define B00101101 45
|
||||
#define B101110 46
|
||||
#define B0101110 46
|
||||
#define B00101110 46
|
||||
#define B101111 47
|
||||
#define B0101111 47
|
||||
#define B00101111 47
|
||||
#define B110000 48
|
||||
#define B0110000 48
|
||||
#define B00110000 48
|
||||
#define B110001 49
|
||||
#define B0110001 49
|
||||
#define B00110001 49
|
||||
#define B110010 50
|
||||
#define B0110010 50
|
||||
#define B00110010 50
|
||||
#define B110011 51
|
||||
#define B0110011 51
|
||||
#define B00110011 51
|
||||
#define B110100 52
|
||||
#define B0110100 52
|
||||
#define B00110100 52
|
||||
#define B110101 53
|
||||
#define B0110101 53
|
||||
#define B00110101 53
|
||||
#define B110110 54
|
||||
#define B0110110 54
|
||||
#define B00110110 54
|
||||
#define B110111 55
|
||||
#define B0110111 55
|
||||
#define B00110111 55
|
||||
#define B111000 56
|
||||
#define B0111000 56
|
||||
#define B00111000 56
|
||||
#define B111001 57
|
||||
#define B0111001 57
|
||||
#define B00111001 57
|
||||
#define B111010 58
|
||||
#define B0111010 58
|
||||
#define B00111010 58
|
||||
#define B111011 59
|
||||
#define B0111011 59
|
||||
#define B00111011 59
|
||||
#define B111100 60
|
||||
#define B0111100 60
|
||||
#define B00111100 60
|
||||
#define B111101 61
|
||||
#define B0111101 61
|
||||
#define B00111101 61
|
||||
#define B111110 62
|
||||
#define B0111110 62
|
||||
#define B00111110 62
|
||||
#define B111111 63
|
||||
#define B0111111 63
|
||||
#define B00111111 63
|
||||
#define B1000000 64
|
||||
#define B01000000 64
|
||||
#define B1000001 65
|
||||
#define B01000001 65
|
||||
#define B1000010 66
|
||||
#define B01000010 66
|
||||
#define B1000011 67
|
||||
#define B01000011 67
|
||||
#define B1000100 68
|
||||
#define B01000100 68
|
||||
#define B1000101 69
|
||||
#define B01000101 69
|
||||
#define B1000110 70
|
||||
#define B01000110 70
|
||||
#define B1000111 71
|
||||
#define B01000111 71
|
||||
#define B1001000 72
|
||||
#define B01001000 72
|
||||
#define B1001001 73
|
||||
#define B01001001 73
|
||||
#define B1001010 74
|
||||
#define B01001010 74
|
||||
#define B1001011 75
|
||||
#define B01001011 75
|
||||
#define B1001100 76
|
||||
#define B01001100 76
|
||||
#define B1001101 77
|
||||
#define B01001101 77
|
||||
#define B1001110 78
|
||||
#define B01001110 78
|
||||
#define B1001111 79
|
||||
#define B01001111 79
|
||||
#define B1010000 80
|
||||
#define B01010000 80
|
||||
#define B1010001 81
|
||||
#define B01010001 81
|
||||
#define B1010010 82
|
||||
#define B01010010 82
|
||||
#define B1010011 83
|
||||
#define B01010011 83
|
||||
#define B1010100 84
|
||||
#define B01010100 84
|
||||
#define B1010101 85
|
||||
#define B01010101 85
|
||||
#define B1010110 86
|
||||
#define B01010110 86
|
||||
#define B1010111 87
|
||||
#define B01010111 87
|
||||
#define B1011000 88
|
||||
#define B01011000 88
|
||||
#define B1011001 89
|
||||
#define B01011001 89
|
||||
#define B1011010 90
|
||||
#define B01011010 90
|
||||
#define B1011011 91
|
||||
#define B01011011 91
|
||||
#define B1011100 92
|
||||
#define B01011100 92
|
||||
#define B1011101 93
|
||||
#define B01011101 93
|
||||
#define B1011110 94
|
||||
#define B01011110 94
|
||||
#define B1011111 95
|
||||
#define B01011111 95
|
||||
#define B1100000 96
|
||||
#define B01100000 96
|
||||
#define B1100001 97
|
||||
#define B01100001 97
|
||||
#define B1100010 98
|
||||
#define B01100010 98
|
||||
#define B1100011 99
|
||||
#define B01100011 99
|
||||
#define B1100100 100
|
||||
#define B01100100 100
|
||||
#define B1100101 101
|
||||
#define B01100101 101
|
||||
#define B1100110 102
|
||||
#define B01100110 102
|
||||
#define B1100111 103
|
||||
#define B01100111 103
|
||||
#define B1101000 104
|
||||
#define B01101000 104
|
||||
#define B1101001 105
|
||||
#define B01101001 105
|
||||
#define B1101010 106
|
||||
#define B01101010 106
|
||||
#define B1101011 107
|
||||
#define B01101011 107
|
||||
#define B1101100 108
|
||||
#define B01101100 108
|
||||
#define B1101101 109
|
||||
#define B01101101 109
|
||||
#define B1101110 110
|
||||
#define B01101110 110
|
||||
#define B1101111 111
|
||||
#define B01101111 111
|
||||
#define B1110000 112
|
||||
#define B01110000 112
|
||||
#define B1110001 113
|
||||
#define B01110001 113
|
||||
#define B1110010 114
|
||||
#define B01110010 114
|
||||
#define B1110011 115
|
||||
#define B01110011 115
|
||||
#define B1110100 116
|
||||
#define B01110100 116
|
||||
#define B1110101 117
|
||||
#define B01110101 117
|
||||
#define B1110110 118
|
||||
#define B01110110 118
|
||||
#define B1110111 119
|
||||
#define B01110111 119
|
||||
#define B1111000 120
|
||||
#define B01111000 120
|
||||
#define B1111001 121
|
||||
#define B01111001 121
|
||||
#define B1111010 122
|
||||
#define B01111010 122
|
||||
#define B1111011 123
|
||||
#define B01111011 123
|
||||
#define B1111100 124
|
||||
#define B01111100 124
|
||||
#define B1111101 125
|
||||
#define B01111101 125
|
||||
#define B1111110 126
|
||||
#define B01111110 126
|
||||
#define B1111111 127
|
||||
#define B01111111 127
|
||||
#define B10000000 128
|
||||
#define B10000001 129
|
||||
#define B10000010 130
|
||||
#define B10000011 131
|
||||
#define B10000100 132
|
||||
#define B10000101 133
|
||||
#define B10000110 134
|
||||
#define B10000111 135
|
||||
#define B10001000 136
|
||||
#define B10001001 137
|
||||
#define B10001010 138
|
||||
#define B10001011 139
|
||||
#define B10001100 140
|
||||
#define B10001101 141
|
||||
#define B10001110 142
|
||||
#define B10001111 143
|
||||
#define B10010000 144
|
||||
#define B10010001 145
|
||||
#define B10010010 146
|
||||
#define B10010011 147
|
||||
#define B10010100 148
|
||||
#define B10010101 149
|
||||
#define B10010110 150
|
||||
#define B10010111 151
|
||||
#define B10011000 152
|
||||
#define B10011001 153
|
||||
#define B10011010 154
|
||||
#define B10011011 155
|
||||
#define B10011100 156
|
||||
#define B10011101 157
|
||||
#define B10011110 158
|
||||
#define B10011111 159
|
||||
#define B10100000 160
|
||||
#define B10100001 161
|
||||
#define B10100010 162
|
||||
#define B10100011 163
|
||||
#define B10100100 164
|
||||
#define B10100101 165
|
||||
#define B10100110 166
|
||||
#define B10100111 167
|
||||
#define B10101000 168
|
||||
#define B10101001 169
|
||||
#define B10101010 170
|
||||
#define B10101011 171
|
||||
#define B10101100 172
|
||||
#define B10101101 173
|
||||
#define B10101110 174
|
||||
#define B10101111 175
|
||||
#define B10110000 176
|
||||
#define B10110001 177
|
||||
#define B10110010 178
|
||||
#define B10110011 179
|
||||
#define B10110100 180
|
||||
#define B10110101 181
|
||||
#define B10110110 182
|
||||
#define B10110111 183
|
||||
#define B10111000 184
|
||||
#define B10111001 185
|
||||
#define B10111010 186
|
||||
#define B10111011 187
|
||||
#define B10111100 188
|
||||
#define B10111101 189
|
||||
#define B10111110 190
|
||||
#define B10111111 191
|
||||
#define B11000000 192
|
||||
#define B11000001 193
|
||||
#define B11000010 194
|
||||
#define B11000011 195
|
||||
#define B11000100 196
|
||||
#define B11000101 197
|
||||
#define B11000110 198
|
||||
#define B11000111 199
|
||||
#define B11001000 200
|
||||
#define B11001001 201
|
||||
#define B11001010 202
|
||||
#define B11001011 203
|
||||
#define B11001100 204
|
||||
#define B11001101 205
|
||||
#define B11001110 206
|
||||
#define B11001111 207
|
||||
#define B11010000 208
|
||||
#define B11010001 209
|
||||
#define B11010010 210
|
||||
#define B11010011 211
|
||||
#define B11010100 212
|
||||
#define B11010101 213
|
||||
#define B11010110 214
|
||||
#define B11010111 215
|
||||
#define B11011000 216
|
||||
#define B11011001 217
|
||||
#define B11011010 218
|
||||
#define B11011011 219
|
||||
#define B11011100 220
|
||||
#define B11011101 221
|
||||
#define B11011110 222
|
||||
#define B11011111 223
|
||||
#define B11100000 224
|
||||
#define B11100001 225
|
||||
#define B11100010 226
|
||||
#define B11100011 227
|
||||
#define B11100100 228
|
||||
#define B11100101 229
|
||||
#define B11100110 230
|
||||
#define B11100111 231
|
||||
#define B11101000 232
|
||||
#define B11101001 233
|
||||
#define B11101010 234
|
||||
#define B11101011 235
|
||||
#define B11101100 236
|
||||
#define B11101101 237
|
||||
#define B11101110 238
|
||||
#define B11101111 239
|
||||
#define B11110000 240
|
||||
#define B11110001 241
|
||||
#define B11110010 242
|
||||
#define B11110011 243
|
||||
#define B11110100 244
|
||||
#define B11110101 245
|
||||
#define B11110110 246
|
||||
#define B11110111 247
|
||||
#define B11111000 248
|
||||
#define B11111001 249
|
||||
#define B11111010 250
|
||||
#define B11111011 251
|
||||
#define B11111100 252
|
||||
#define B11111101 253
|
||||
#define B11111110 254
|
||||
#define B11111111 255
|
||||
|
||||
#endif
|
||||
|
|
@ -1,133 +0,0 @@
|
|||
/*
|
||||
Arduino.h - Main include file for the Arduino SDK
|
||||
Copyright (c) 2005-2013 Arduino Team. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "soc/soc_caps.h"
|
||||
#if SOC_ADC_SUPPORTED
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "esp32-hal.h"
|
||||
|
||||
typedef enum {
|
||||
ADC_0db,
|
||||
ADC_2_5db,
|
||||
ADC_6db,
|
||||
ADC_11db,
|
||||
ADC_ATTENDB_MAX
|
||||
} adc_attenuation_t;
|
||||
|
||||
/*
|
||||
* Get ADC value for pin
|
||||
* */
|
||||
uint16_t analogRead(uint8_t pin);
|
||||
|
||||
/*
|
||||
* Get MilliVolts value for pin
|
||||
* */
|
||||
uint32_t analogReadMilliVolts(uint8_t pin);
|
||||
|
||||
/*
|
||||
* Set the resolution of analogRead return values. Default is 12 bits (range from 0 to 4096).
|
||||
* If between 9 and 12, it will equal the set hardware resolution, else value will be shifted.
|
||||
* Range is 1 - 16
|
||||
*
|
||||
* Note: compatibility with Arduino SAM
|
||||
*/
|
||||
void analogReadResolution(uint8_t bits);
|
||||
|
||||
/*
|
||||
* Set the attenuation for all channels
|
||||
* Default is 11db
|
||||
* */
|
||||
void analogSetAttenuation(adc_attenuation_t attenuation);
|
||||
|
||||
/*
|
||||
* Set the attenuation for particular pin
|
||||
* Default is 11db
|
||||
* */
|
||||
void analogSetPinAttenuation(uint8_t pin, adc_attenuation_t attenuation);
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
/*
|
||||
* Sets the sample bits and read resolution
|
||||
* Default is 12bit (0 - 4095)
|
||||
* Range is 9 - 12
|
||||
* */
|
||||
void analogSetWidth(uint8_t bits);
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Analog Continuous mode
|
||||
* */
|
||||
|
||||
typedef struct {
|
||||
uint8_t pin; /*!<ADC pin */
|
||||
uint8_t channel; /*!<ADC channel */
|
||||
int avg_read_raw; /*!<ADC average raw data */
|
||||
int avg_read_mvolts; /*!<ADC average voltage in mV */
|
||||
} adc_continuous_data_t;
|
||||
|
||||
/*
|
||||
* Setup ADC continuous peripheral
|
||||
* */
|
||||
bool analogContinuous(const uint8_t pins[], size_t pins_count, uint32_t conversions_per_pin, uint32_t sampling_freq_hz, void (*userFunc)(void));
|
||||
|
||||
/*
|
||||
* Read ADC continuous conversion data
|
||||
* */
|
||||
bool analogContinuousRead(adc_continuous_data_t **buffer, uint32_t timeout_ms);
|
||||
|
||||
/*
|
||||
* Start ADC continuous conversions
|
||||
* */
|
||||
bool analogContinuousStart();
|
||||
|
||||
/*
|
||||
* Stop ADC continuous conversions
|
||||
* */
|
||||
bool analogContinuousStop();
|
||||
|
||||
/*
|
||||
* Deinitialize ADC continuous peripheral
|
||||
* */
|
||||
bool analogContinuousDeinit();
|
||||
|
||||
/*
|
||||
* Sets the attenuation for continuous mode reading
|
||||
* Default is 11db
|
||||
* */
|
||||
void analogContinuousSetAtten(adc_attenuation_t attenuation);
|
||||
|
||||
/*
|
||||
* Sets the read resolution for continuous mode
|
||||
* Default is 12bit (0 - 4095)
|
||||
* Range is 9 - 12
|
||||
* */
|
||||
void analogContinuousSetWidth(uint8_t bits);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SOC_ADC_SUPPORTED */
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// 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.
|
||||
|
||||
#ifndef _ESP32_ESP32_HAL_BT_H_
|
||||
#define _ESP32_ESP32_HAL_BT_H_
|
||||
|
||||
#include "soc/soc_caps.h"
|
||||
#if SOC_BT_SUPPORTED
|
||||
|
||||
#include "esp32-hal.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
BT_MODE_DEFAULT,
|
||||
BT_MODE_BLE,
|
||||
BT_MODE_CLASSIC_BT,
|
||||
BT_MODE_BTDM
|
||||
} bt_mode;
|
||||
|
||||
bool btStarted();
|
||||
bool btStart();
|
||||
bool btStartMode(bt_mode mode);
|
||||
bool btStop();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SOC_BT_SUPPORTED */
|
||||
|
||||
#endif /* _ESP32_ESP32_HAL_BT_H_ */
|
||||
|
|
@ -1,293 +0,0 @@
|
|||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// 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.
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_log.h"
|
||||
#include "soc/rtc.h"
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32C2) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32H2)
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
#include "soc/apb_ctrl_reg.h"
|
||||
#endif
|
||||
#include "soc/efuse_reg.h"
|
||||
#include "esp32-hal.h"
|
||||
#include "esp32-hal-cpu.h"
|
||||
|
||||
#include "esp_system.h"
|
||||
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
|
||||
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
|
||||
#include "freertos/xtensa_timer.h"
|
||||
#include "esp32/rom/rtc.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#include "freertos/xtensa_timer.h"
|
||||
#include "esp32s2/rom/rtc.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
#include "freertos/xtensa_timer.h"
|
||||
#include "esp32s3/rom/rtc.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32C2
|
||||
#include "esp32c2/rom/rtc.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||
#include "esp32c3/rom/rtc.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32C6
|
||||
#include "esp32c6/rom/rtc.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||
#include "esp32h2/rom/rtc.h"
|
||||
#else
|
||||
#error Target CONFIG_IDF_TARGET is not supported
|
||||
#endif
|
||||
#else // ESP32 Before IDF 4.0
|
||||
#include "rom/rtc.h"
|
||||
#endif
|
||||
|
||||
typedef struct apb_change_cb_s {
|
||||
struct apb_change_cb_s *prev;
|
||||
struct apb_change_cb_s *next;
|
||||
void *arg;
|
||||
apb_change_cb_t cb;
|
||||
} apb_change_t;
|
||||
|
||||
static apb_change_t *apb_change_callbacks = NULL;
|
||||
static SemaphoreHandle_t apb_change_lock = NULL;
|
||||
|
||||
static void initApbChangeCallback() {
|
||||
static volatile bool initialized = false;
|
||||
if (!initialized) {
|
||||
initialized = true;
|
||||
apb_change_lock = xSemaphoreCreateMutex();
|
||||
if (!apb_change_lock) {
|
||||
initialized = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void triggerApbChangeCallback(apb_change_ev_t ev_type, uint32_t old_apb, uint32_t new_apb) {
|
||||
initApbChangeCallback();
|
||||
xSemaphoreTake(apb_change_lock, portMAX_DELAY);
|
||||
apb_change_t *r = apb_change_callbacks;
|
||||
if (r != NULL) {
|
||||
if (ev_type == APB_BEFORE_CHANGE) {
|
||||
while (r != NULL) {
|
||||
r->cb(r->arg, ev_type, old_apb, new_apb);
|
||||
r = r->next;
|
||||
}
|
||||
} else { // run backwards through chain
|
||||
while (r->next != NULL) {
|
||||
r = r->next; // find first added
|
||||
}
|
||||
while (r != NULL) {
|
||||
r->cb(r->arg, ev_type, old_apb, new_apb);
|
||||
r = r->prev;
|
||||
}
|
||||
}
|
||||
}
|
||||
xSemaphoreGive(apb_change_lock);
|
||||
}
|
||||
|
||||
bool addApbChangeCallback(void *arg, apb_change_cb_t cb) {
|
||||
initApbChangeCallback();
|
||||
apb_change_t *c = (apb_change_t *)malloc(sizeof(apb_change_t));
|
||||
if (!c) {
|
||||
log_e("Callback Object Malloc Failed");
|
||||
return false;
|
||||
}
|
||||
c->next = NULL;
|
||||
c->prev = NULL;
|
||||
c->arg = arg;
|
||||
c->cb = cb;
|
||||
xSemaphoreTake(apb_change_lock, portMAX_DELAY);
|
||||
if (apb_change_callbacks == NULL) {
|
||||
apb_change_callbacks = c;
|
||||
} else {
|
||||
apb_change_t *r = apb_change_callbacks;
|
||||
// look for duplicate callbacks
|
||||
while ((r != NULL) && !((r->cb == cb) && (r->arg == arg))) {
|
||||
r = r->next;
|
||||
}
|
||||
if (r) {
|
||||
log_e("duplicate func=%8p arg=%8p", c->cb, c->arg);
|
||||
free(c);
|
||||
xSemaphoreGive(apb_change_lock);
|
||||
return false;
|
||||
} else {
|
||||
c->next = apb_change_callbacks;
|
||||
apb_change_callbacks->prev = c;
|
||||
apb_change_callbacks = c;
|
||||
}
|
||||
}
|
||||
xSemaphoreGive(apb_change_lock);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool removeApbChangeCallback(void *arg, apb_change_cb_t cb) {
|
||||
initApbChangeCallback();
|
||||
xSemaphoreTake(apb_change_lock, portMAX_DELAY);
|
||||
apb_change_t *r = apb_change_callbacks;
|
||||
// look for matching callback
|
||||
while ((r != NULL) && !((r->cb == cb) && (r->arg == arg))) {
|
||||
r = r->next;
|
||||
}
|
||||
if (r == NULL) {
|
||||
log_e("not found func=%8p arg=%8p", cb, arg);
|
||||
xSemaphoreGive(apb_change_lock);
|
||||
return false;
|
||||
} else {
|
||||
// patch links
|
||||
if (r->prev) {
|
||||
r->prev->next = r->next;
|
||||
} else { // this is first link
|
||||
apb_change_callbacks = r->next;
|
||||
}
|
||||
if (r->next) {
|
||||
r->next->prev = r->prev;
|
||||
}
|
||||
free(r);
|
||||
}
|
||||
xSemaphoreGive(apb_change_lock);
|
||||
return true;
|
||||
}
|
||||
|
||||
static uint32_t calculateApb(rtc_cpu_freq_config_t *conf) {
|
||||
#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32H2
|
||||
return APB_CLK_FREQ;
|
||||
#else
|
||||
if (conf->freq_mhz >= 80) {
|
||||
return 80 * MHZ;
|
||||
}
|
||||
return (conf->source_freq_mhz * MHZ) / conf->div;
|
||||
#endif
|
||||
}
|
||||
|
||||
void esp_timer_impl_update_apb_freq(uint32_t apb_ticks_per_us); //private in IDF
|
||||
|
||||
bool setCpuFrequencyMhz(uint32_t cpu_freq_mhz) {
|
||||
rtc_cpu_freq_config_t conf, cconf;
|
||||
uint32_t capb, apb;
|
||||
//Get XTAL Frequency and calculate min CPU MHz
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32H2
|
||||
rtc_xtal_freq_t xtal = rtc_clk_xtal_freq_get();
|
||||
#endif
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
if (xtal > RTC_XTAL_FREQ_AUTO) {
|
||||
if (xtal < RTC_XTAL_FREQ_40M) {
|
||||
if (cpu_freq_mhz <= xtal && cpu_freq_mhz != xtal && cpu_freq_mhz != (xtal / 2)) {
|
||||
log_e("Bad frequency: %u MHz! Options are: 240, 160, 80, %u and %u MHz", cpu_freq_mhz, xtal, xtal / 2);
|
||||
return false;
|
||||
}
|
||||
} else if (cpu_freq_mhz <= xtal && cpu_freq_mhz != xtal && cpu_freq_mhz != (xtal / 2) && cpu_freq_mhz != (xtal / 4)) {
|
||||
log_e("Bad frequency: %u MHz! Options are: 240, 160, 80, %u, %u and %u MHz", cpu_freq_mhz, xtal, xtal / 2, xtal / 4);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32H2
|
||||
if (cpu_freq_mhz > xtal && cpu_freq_mhz != 240 && cpu_freq_mhz != 160 && cpu_freq_mhz != 120 && cpu_freq_mhz != 80) {
|
||||
if (xtal >= RTC_XTAL_FREQ_40M) {
|
||||
log_e("Bad frequency: %u MHz! Options are: 240, 160, 120, 80, %u, %u and %u MHz", cpu_freq_mhz, xtal, xtal / 2, xtal / 4);
|
||||
} else {
|
||||
log_e("Bad frequency: %u MHz! Options are: 240, 160, 120, 80, %u and %u MHz", cpu_freq_mhz, xtal, xtal / 2);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
//check if cpu supports the frequency
|
||||
if (cpu_freq_mhz == 240) {
|
||||
//Check if ESP32 is rated for a CPU frequency of 160MHz only
|
||||
if (REG_GET_BIT(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_CPU_FREQ_RATED) && REG_GET_BIT(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_CPU_FREQ_LOW)) {
|
||||
log_e("Can not switch to 240 MHz! Chip CPU frequency rated for 160MHz.");
|
||||
cpu_freq_mhz = 160;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
//Get current CPU clock configuration
|
||||
rtc_clk_cpu_freq_get_config(&cconf);
|
||||
//return if frequency has not changed
|
||||
if (cconf.freq_mhz == cpu_freq_mhz) {
|
||||
return true;
|
||||
}
|
||||
//Get configuration for the new CPU frequency
|
||||
if (!rtc_clk_cpu_freq_mhz_to_config(cpu_freq_mhz, &conf)) {
|
||||
log_e("CPU clock could not be set to %u MHz", cpu_freq_mhz);
|
||||
return false;
|
||||
}
|
||||
//Current APB
|
||||
capb = calculateApb(&cconf);
|
||||
//New APB
|
||||
apb = calculateApb(&conf);
|
||||
|
||||
//Call peripheral functions before the APB change
|
||||
if (apb_change_callbacks) {
|
||||
triggerApbChangeCallback(APB_BEFORE_CHANGE, capb, apb);
|
||||
}
|
||||
//Make the frequency change
|
||||
rtc_clk_cpu_freq_set_config_fast(&conf);
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32C2) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32H2)
|
||||
if (capb != apb) {
|
||||
//Update REF_TICK (uncomment if REF_TICK is different than 1MHz)
|
||||
//if(conf.freq_mhz < 80){
|
||||
// ESP_REG(APB_CTRL_XTAL_TICK_CONF_REG) = conf.freq_mhz / (REF_CLK_FREQ / MHZ) - 1;
|
||||
// }
|
||||
//Update APB Freq REG
|
||||
rtc_clk_apb_freq_update(apb);
|
||||
//Update esp_timer divisor
|
||||
esp_timer_impl_update_apb_freq(apb / MHZ);
|
||||
}
|
||||
#endif
|
||||
//Update FreeRTOS Tick Divisor
|
||||
#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
|
||||
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
|
||||
#else
|
||||
uint32_t fcpu = (conf.freq_mhz >= 80) ? (conf.freq_mhz * MHZ) : (apb);
|
||||
_xt_tick_divisor = fcpu / XT_TICK_PER_SEC;
|
||||
#endif
|
||||
//Call peripheral functions after the APB change
|
||||
if (apb_change_callbacks) {
|
||||
triggerApbChangeCallback(APB_AFTER_CHANGE, capb, apb);
|
||||
}
|
||||
#ifdef SOC_CLK_APLL_SUPPORTED
|
||||
log_d(
|
||||
"%s: %u / %u = %u Mhz, APB: %u Hz",
|
||||
(conf.source == RTC_CPU_FREQ_SRC_PLL) ? "PLL"
|
||||
: ((conf.source == RTC_CPU_FREQ_SRC_APLL) ? "APLL" : ((conf.source == RTC_CPU_FREQ_SRC_XTAL) ? "XTAL" : "8M")),
|
||||
conf.source_freq_mhz, conf.div, conf.freq_mhz, apb
|
||||
);
|
||||
#else
|
||||
log_d(
|
||||
"%s: %u / %u = %u Mhz, APB: %u Hz", (conf.source == RTC_CPU_FREQ_SRC_PLL) ? "PLL" : ((conf.source == RTC_CPU_FREQ_SRC_XTAL) ? "XTAL" : "17.5M"),
|
||||
conf.source_freq_mhz, conf.div, conf.freq_mhz, apb
|
||||
);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t getCpuFrequencyMhz() {
|
||||
rtc_cpu_freq_config_t conf;
|
||||
rtc_clk_cpu_freq_get_config(&conf);
|
||||
return conf.freq_mhz;
|
||||
}
|
||||
|
||||
uint32_t getXtalFrequencyMhz() {
|
||||
return rtc_clk_xtal_freq_get();
|
||||
}
|
||||
|
||||
uint32_t getApbFrequency() {
|
||||
rtc_cpu_freq_config_t conf;
|
||||
rtc_clk_cpu_freq_get_config(&conf);
|
||||
return calculateApb(&conf);
|
||||
}
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// 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.
|
||||
|
||||
#ifndef _ESP32_HAL_CPU_H_
|
||||
#define _ESP32_HAL_CPU_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef enum {
|
||||
APB_BEFORE_CHANGE,
|
||||
APB_AFTER_CHANGE
|
||||
} apb_change_ev_t;
|
||||
|
||||
typedef void (*apb_change_cb_t)(void *arg, apb_change_ev_t ev_type, uint32_t old_apb, uint32_t new_apb);
|
||||
|
||||
bool addApbChangeCallback(void *arg, apb_change_cb_t cb);
|
||||
bool removeApbChangeCallback(void *arg, apb_change_cb_t cb);
|
||||
|
||||
//function takes the following frequencies as valid values:
|
||||
// 240, 160, 80 <<< For all XTAL types
|
||||
// 40, 20, 10 <<< For 40MHz XTAL
|
||||
// 26, 13 <<< For 26MHz XTAL
|
||||
// 24, 12 <<< For 24MHz XTAL
|
||||
bool setCpuFrequencyMhz(uint32_t cpu_freq_mhz);
|
||||
|
||||
uint32_t getCpuFrequencyMhz(); // In MHz
|
||||
uint32_t getXtalFrequencyMhz(); // In MHz
|
||||
uint32_t getApbFrequency(); // In Hz
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ESP32_HAL_CPU_H_ */
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "soc/soc_caps.h"
|
||||
#if SOC_DAC_SUPPORTED
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
bool dacWrite(uint8_t pin, uint8_t value);
|
||||
bool dacDisable(uint8_t pin);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SOC_DAC_SUPPORTED */
|
||||
|
|
@ -1,281 +0,0 @@
|
|||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// 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.
|
||||
|
||||
#include "esp32-hal-gpio.h"
|
||||
#include "esp32-hal-periman.h"
|
||||
#include "hal/gpio_hal.h"
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
// RGB_BUILTIN is defined in pins_arduino.h
|
||||
// If RGB_BUILTIN is defined, it will be used as a pin number for the RGB LED
|
||||
// If RGB_BUILTIN has a side effect that prevents using RMT Legacy driver in IDF 5.1
|
||||
// Define ESP32_ARDUINO_NO_RGB_BUILTIN in build_opt.h or through CLI to disable RGB_BUILTIN
|
||||
#ifdef ESP32_ARDUINO_NO_RGB_BUILTIN
|
||||
#ifdef RGB_BUILTIN
|
||||
#undef RGB_BUILTIN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// It fixes lack of pin definition for S3 and for any future SoC
|
||||
// this function works for ESP32, ESP32-S2 and ESP32-S3 - including the C3, it will return -1 for any pin
|
||||
#if SOC_TOUCH_SENSOR_NUM > 0
|
||||
#include "soc/touch_sensor_periph.h"
|
||||
|
||||
int8_t digitalPinToTouchChannel(uint8_t pin) {
|
||||
int8_t ret = -1;
|
||||
if (pin < SOC_GPIO_PIN_COUNT) {
|
||||
for (uint8_t i = 0; i < SOC_TOUCH_SENSOR_NUM; i++) {
|
||||
if (touch_sensor_channel_io_map[i] == pin) {
|
||||
ret = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
// No Touch Sensor available
|
||||
int8_t digitalPinToTouchChannel(uint8_t pin) {
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SOC_ADC_SUPPORTED
|
||||
#include "soc/adc_periph.h"
|
||||
|
||||
int8_t digitalPinToAnalogChannel(uint8_t pin) {
|
||||
uint8_t channel = 0;
|
||||
if (pin < SOC_GPIO_PIN_COUNT) {
|
||||
for (uint8_t i = 0; i < SOC_ADC_PERIPH_NUM; i++) {
|
||||
for (uint8_t j = 0; j < SOC_ADC_MAX_CHANNEL_NUM; j++) {
|
||||
if (adc_channel_io_map[i][j] == pin) {
|
||||
return channel;
|
||||
}
|
||||
channel++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int8_t analogChannelToDigitalPin(uint8_t channel) {
|
||||
if (channel >= (SOC_ADC_PERIPH_NUM * SOC_ADC_MAX_CHANNEL_NUM)) {
|
||||
return -1;
|
||||
}
|
||||
uint8_t adc_unit = (channel / SOC_ADC_MAX_CHANNEL_NUM);
|
||||
uint8_t adc_chan = (channel % SOC_ADC_MAX_CHANNEL_NUM);
|
||||
return adc_channel_io_map[adc_unit][adc_chan];
|
||||
}
|
||||
#else
|
||||
// No Analog channels available
|
||||
int8_t analogChannelToDigitalPin(uint8_t channel) {
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
typedef void (*voidFuncPtr)(void);
|
||||
typedef void (*voidFuncPtrArg)(void *);
|
||||
typedef struct {
|
||||
voidFuncPtr fn;
|
||||
void *arg;
|
||||
bool functional;
|
||||
} InterruptHandle_t;
|
||||
static InterruptHandle_t __pinInterruptHandlers[SOC_GPIO_PIN_COUNT] = {
|
||||
0,
|
||||
};
|
||||
|
||||
#include "driver/rtc_io.h"
|
||||
|
||||
static bool gpioDetachBus(void *bus) {
|
||||
return true;
|
||||
}
|
||||
|
||||
extern void ARDUINO_ISR_ATTR __pinMode(uint8_t pin, uint8_t mode) {
|
||||
#ifdef RGB_BUILTIN
|
||||
if (pin == RGB_BUILTIN) {
|
||||
__pinMode(RGB_BUILTIN - SOC_GPIO_PIN_COUNT, mode);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (pin >= SOC_GPIO_PIN_COUNT) {
|
||||
log_e("Invalid IO %i selected", pin);
|
||||
return;
|
||||
}
|
||||
|
||||
if (perimanGetPinBus(pin, ESP32_BUS_TYPE_GPIO) == NULL) {
|
||||
perimanSetBusDeinit(ESP32_BUS_TYPE_GPIO, gpioDetachBus);
|
||||
if (!perimanClearPinBus(pin)) {
|
||||
log_e("Deinit of previous bus from IO %i failed", pin);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
gpio_hal_context_t gpiohal;
|
||||
gpiohal.dev = GPIO_LL_GET_HW(GPIO_PORT_0);
|
||||
|
||||
gpio_config_t conf = {
|
||||
.pin_bit_mask = (1ULL << pin), /*!< GPIO pin: set with bit mask, each bit maps to a GPIO */
|
||||
.mode = GPIO_MODE_DISABLE, /*!< GPIO mode: set input/output mode */
|
||||
.pull_up_en = GPIO_PULLUP_DISABLE, /*!< GPIO pull-up */
|
||||
.pull_down_en = GPIO_PULLDOWN_DISABLE, /*!< GPIO pull-down */
|
||||
.intr_type = gpiohal.dev->pin[pin].int_type /*!< GPIO interrupt type - previously set */
|
||||
};
|
||||
if (mode < 0x20) { //io
|
||||
conf.mode = mode & (INPUT | OUTPUT);
|
||||
if (mode & OPEN_DRAIN) {
|
||||
conf.mode |= GPIO_MODE_DEF_OD;
|
||||
}
|
||||
if (mode & PULLUP) {
|
||||
conf.pull_up_en = GPIO_PULLUP_ENABLE;
|
||||
}
|
||||
if (mode & PULLDOWN) {
|
||||
conf.pull_down_en = GPIO_PULLDOWN_ENABLE;
|
||||
}
|
||||
}
|
||||
if (gpio_config(&conf) != ESP_OK) {
|
||||
log_e("IO %i config failed", pin);
|
||||
return;
|
||||
}
|
||||
if (perimanGetPinBus(pin, ESP32_BUS_TYPE_GPIO) == NULL) {
|
||||
if (!perimanSetPinBus(pin, ESP32_BUS_TYPE_GPIO, (void *)(pin + 1), -1, -1)) {
|
||||
//gpioDetachBus((void *)(pin+1));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef RGB_BUILTIN
|
||||
uint8_t RGB_BUILTIN_storage = 0;
|
||||
#endif
|
||||
|
||||
extern void ARDUINO_ISR_ATTR __digitalWrite(uint8_t pin, uint8_t val) {
|
||||
#ifdef RGB_BUILTIN
|
||||
if (pin == RGB_BUILTIN) {
|
||||
//use RMT to set all channels on/off
|
||||
RGB_BUILTIN_storage = val;
|
||||
const uint8_t comm_val = val != 0 ? RGB_BRIGHTNESS : 0;
|
||||
neopixelWrite(RGB_BUILTIN, comm_val, comm_val, comm_val);
|
||||
return;
|
||||
}
|
||||
#endif // RGB_BUILTIN
|
||||
if (perimanGetPinBus(pin, ESP32_BUS_TYPE_GPIO) != NULL) {
|
||||
gpio_set_level((gpio_num_t)pin, val);
|
||||
} else {
|
||||
log_e("IO %i is not set as GPIO.", pin);
|
||||
}
|
||||
}
|
||||
|
||||
extern int ARDUINO_ISR_ATTR __digitalRead(uint8_t pin) {
|
||||
#ifdef RGB_BUILTIN
|
||||
if (pin == RGB_BUILTIN) {
|
||||
return RGB_BUILTIN_storage;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (perimanGetPinBus(pin, ESP32_BUS_TYPE_GPIO) != NULL) {
|
||||
return gpio_get_level((gpio_num_t)pin);
|
||||
} else {
|
||||
log_e("IO %i is not set as GPIO.", pin);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void ARDUINO_ISR_ATTR __onPinInterrupt(void *arg) {
|
||||
InterruptHandle_t *isr = (InterruptHandle_t *)arg;
|
||||
if (isr->fn) {
|
||||
if (isr->arg) {
|
||||
((voidFuncPtrArg)isr->fn)(isr->arg);
|
||||
} else {
|
||||
isr->fn();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern void cleanupFunctional(void *arg);
|
||||
|
||||
extern void __attachInterruptFunctionalArg(uint8_t pin, voidFuncPtrArg userFunc, void *arg, int intr_type, bool functional) {
|
||||
static bool interrupt_initialized = false;
|
||||
|
||||
// makes sure that pin -1 (255) will never work -- this follows Arduino standard
|
||||
if (pin >= SOC_GPIO_PIN_COUNT) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!interrupt_initialized) {
|
||||
esp_err_t err = gpio_install_isr_service((int)ARDUINO_ISR_FLAG);
|
||||
interrupt_initialized = (err == ESP_OK) || (err == ESP_ERR_INVALID_STATE);
|
||||
}
|
||||
if (!interrupt_initialized) {
|
||||
log_e("IO %i ISR Service Failed To Start", pin);
|
||||
return;
|
||||
}
|
||||
|
||||
// if new attach without detach remove old info
|
||||
if (__pinInterruptHandlers[pin].functional && __pinInterruptHandlers[pin].arg) {
|
||||
cleanupFunctional(__pinInterruptHandlers[pin].arg);
|
||||
}
|
||||
__pinInterruptHandlers[pin].fn = (voidFuncPtr)userFunc;
|
||||
__pinInterruptHandlers[pin].arg = arg;
|
||||
__pinInterruptHandlers[pin].functional = functional;
|
||||
|
||||
gpio_set_intr_type((gpio_num_t)pin, (gpio_int_type_t)(intr_type & 0x7));
|
||||
if (intr_type & 0x8) {
|
||||
gpio_wakeup_enable((gpio_num_t)pin, (gpio_int_type_t)(intr_type & 0x7));
|
||||
}
|
||||
gpio_isr_handler_add((gpio_num_t)pin, __onPinInterrupt, &__pinInterruptHandlers[pin]);
|
||||
|
||||
//FIX interrupts on peripherals outputs (eg. LEDC,...)
|
||||
//Enable input in GPIO register
|
||||
gpio_hal_context_t gpiohal;
|
||||
gpiohal.dev = GPIO_LL_GET_HW(GPIO_PORT_0);
|
||||
gpio_hal_input_enable(&gpiohal, pin);
|
||||
}
|
||||
|
||||
extern void __attachInterruptArg(uint8_t pin, voidFuncPtrArg userFunc, void *arg, int intr_type) {
|
||||
__attachInterruptFunctionalArg(pin, userFunc, arg, intr_type, false);
|
||||
}
|
||||
|
||||
extern void __attachInterrupt(uint8_t pin, voidFuncPtr userFunc, int intr_type) {
|
||||
__attachInterruptFunctionalArg(pin, (voidFuncPtrArg)userFunc, NULL, intr_type, false);
|
||||
}
|
||||
|
||||
extern void __detachInterrupt(uint8_t pin) {
|
||||
gpio_isr_handler_remove((gpio_num_t)pin); //remove handle and disable isr for pin
|
||||
gpio_wakeup_disable((gpio_num_t)pin);
|
||||
|
||||
if (__pinInterruptHandlers[pin].functional && __pinInterruptHandlers[pin].arg) {
|
||||
cleanupFunctional(__pinInterruptHandlers[pin].arg);
|
||||
}
|
||||
__pinInterruptHandlers[pin].fn = NULL;
|
||||
__pinInterruptHandlers[pin].arg = NULL;
|
||||
__pinInterruptHandlers[pin].functional = false;
|
||||
|
||||
gpio_set_intr_type((gpio_num_t)pin, GPIO_INTR_DISABLE);
|
||||
}
|
||||
|
||||
extern void enableInterrupt(uint8_t pin) {
|
||||
gpio_intr_enable((gpio_num_t)pin);
|
||||
}
|
||||
|
||||
extern void disableInterrupt(uint8_t pin) {
|
||||
gpio_intr_disable((gpio_num_t)pin);
|
||||
}
|
||||
|
||||
extern void pinMode(uint8_t pin, uint8_t mode) __attribute__((weak, alias("__pinMode")));
|
||||
extern void digitalWrite(uint8_t pin, uint8_t val) __attribute__((weak, alias("__digitalWrite")));
|
||||
extern int digitalRead(uint8_t pin) __attribute__((weak, alias("__digitalRead")));
|
||||
extern void attachInterrupt(uint8_t pin, voidFuncPtr handler, int mode) __attribute__((weak, alias("__attachInterrupt")));
|
||||
extern void attachInterruptArg(uint8_t pin, voidFuncPtrArg handler, void *arg, int mode) __attribute__((weak, alias("__attachInterruptArg")));
|
||||
extern void detachInterrupt(uint8_t pin) __attribute__((weak, alias("__detachInterrupt")));
|
||||
|
|
@ -1,92 +0,0 @@
|
|||
/*
|
||||
Arduino.h - Main include file for the Arduino SDK
|
||||
Copyright (c) 2005-2013 Arduino Team. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef MAIN_ESP32_HAL_GPIO_H_
|
||||
#define MAIN_ESP32_HAL_GPIO_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "esp32-hal.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "pins_arduino.h"
|
||||
#include "driver/gpio.h"
|
||||
|
||||
#if (CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
|
||||
#define NUM_OUPUT_PINS 46
|
||||
#define PIN_DAC1 17
|
||||
#define PIN_DAC2 18
|
||||
#else
|
||||
#define NUM_OUPUT_PINS 34
|
||||
#define PIN_DAC1 25
|
||||
#define PIN_DAC2 26
|
||||
#endif
|
||||
|
||||
#define LOW 0x0
|
||||
#define HIGH 0x1
|
||||
|
||||
//GPIO FUNCTIONS
|
||||
#define INPUT 0x01
|
||||
// Changed OUTPUT from 0x02 to behave the same as Arduino pinMode(pin,OUTPUT)
|
||||
// where you can read the state of pin even when it is set as OUTPUT
|
||||
#define OUTPUT 0x03
|
||||
#define PULLUP 0x04
|
||||
#define INPUT_PULLUP 0x05
|
||||
#define PULLDOWN 0x08
|
||||
#define INPUT_PULLDOWN 0x09
|
||||
#define OPEN_DRAIN 0x10
|
||||
#define OUTPUT_OPEN_DRAIN 0x13
|
||||
#define ANALOG 0xC0
|
||||
|
||||
//Interrupt Modes
|
||||
#define DISABLED 0x00
|
||||
#define RISING 0x01
|
||||
#define FALLING 0x02
|
||||
#define CHANGE 0x03
|
||||
#define ONLOW 0x04
|
||||
#define ONHIGH 0x05
|
||||
#define ONLOW_WE 0x0C
|
||||
#define ONHIGH_WE 0x0D
|
||||
|
||||
#define digitalPinIsValid(pin) GPIO_IS_VALID_GPIO(pin)
|
||||
#define digitalPinCanOutput(pin) GPIO_IS_VALID_OUTPUT_GPIO(pin)
|
||||
|
||||
#define digitalPinToRtcPin(pin) ((RTC_GPIO_IS_VALID_GPIO(pin)) ? rtc_io_number_get(pin) : -1)
|
||||
#define digitalPinToDacChannel(pin) (((pin) == DAC_CHANNEL_1_GPIO_NUM) ? 0 : ((pin) == DAC_CHANNEL_2_GPIO_NUM) ? 1 : -1)
|
||||
|
||||
void pinMode(uint8_t pin, uint8_t mode);
|
||||
void digitalWrite(uint8_t pin, uint8_t val);
|
||||
int digitalRead(uint8_t pin);
|
||||
|
||||
void attachInterrupt(uint8_t pin, void (*)(void), int mode);
|
||||
void attachInterruptArg(uint8_t pin, void (*)(void *), void *arg, int mode);
|
||||
void detachInterrupt(uint8_t pin);
|
||||
void enableInterrupt(uint8_t pin);
|
||||
void disableInterrupt(uint8_t pin);
|
||||
|
||||
int8_t digitalPinToTouchChannel(uint8_t pin);
|
||||
int8_t digitalPinToAnalogChannel(uint8_t pin);
|
||||
int8_t analogChannelToDigitalPin(uint8_t channel);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* MAIN_ESP32_HAL_GPIO_H_ */
|
||||
|
|
@ -1,871 +0,0 @@
|
|||
// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// 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.
|
||||
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#if SOC_I2C_SUPPORT_SLAVE
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_attr.h"
|
||||
#include "rom/gpio.h"
|
||||
#include "soc/gpio_sig_map.h"
|
||||
#include "hal/gpio_types.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/ringbuf.h"
|
||||
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "soc/i2c_reg.h"
|
||||
#include "soc/i2c_struct.h"
|
||||
#include "hal/i2c_ll.h"
|
||||
#include "hal/clk_gate_ll.h"
|
||||
#include "esp32-hal-log.h"
|
||||
#include "esp32-hal-i2c-slave.h"
|
||||
#include "esp32-hal-periman.h"
|
||||
|
||||
#define I2C_SLAVE_USE_RX_QUEUE 0 // 1: Queue, 0: RingBuffer
|
||||
|
||||
#if SOC_I2C_NUM > 1
|
||||
#define I2C_SCL_IDX(p) ((p == 0) ? I2CEXT0_SCL_OUT_IDX : ((p == 1) ? I2CEXT1_SCL_OUT_IDX : 0))
|
||||
#define I2C_SDA_IDX(p) ((p == 0) ? I2CEXT0_SDA_OUT_IDX : ((p == 1) ? I2CEXT1_SDA_OUT_IDX : 0))
|
||||
#else
|
||||
#define I2C_SCL_IDX(p) I2CEXT0_SCL_OUT_IDX
|
||||
#define I2C_SDA_IDX(p) I2CEXT0_SDA_OUT_IDX
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#define I2C_TXFIFO_WM_INT_ENA I2C_TXFIFO_EMPTY_INT_ENA
|
||||
#define I2C_RXFIFO_WM_INT_ENA I2C_RXFIFO_FULL_INT_ENA
|
||||
#endif
|
||||
|
||||
enum {
|
||||
I2C_SLAVE_EVT_RX,
|
||||
I2C_SLAVE_EVT_TX
|
||||
};
|
||||
|
||||
typedef struct i2c_slave_struct_t {
|
||||
i2c_dev_t *dev;
|
||||
uint8_t num;
|
||||
int8_t sda;
|
||||
int8_t scl;
|
||||
i2c_slave_request_cb_t request_callback;
|
||||
i2c_slave_receive_cb_t receive_callback;
|
||||
void *arg;
|
||||
intr_handle_t intr_handle;
|
||||
TaskHandle_t task_handle;
|
||||
QueueHandle_t event_queue;
|
||||
#if I2C_SLAVE_USE_RX_QUEUE
|
||||
QueueHandle_t rx_queue;
|
||||
#else
|
||||
RingbufHandle_t rx_ring_buf;
|
||||
#endif
|
||||
QueueHandle_t tx_queue;
|
||||
uint32_t rx_data_count;
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
SemaphoreHandle_t lock;
|
||||
#endif
|
||||
} i2c_slave_struct_t;
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
uint32_t event : 2;
|
||||
uint32_t stop : 1;
|
||||
uint32_t param : 29;
|
||||
};
|
||||
uint32_t val;
|
||||
} i2c_slave_queue_event_t;
|
||||
|
||||
static i2c_slave_struct_t _i2c_bus_array[SOC_I2C_NUM] = {
|
||||
{&I2C0, 0, -1, -1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
,
|
||||
NULL
|
||||
#endif
|
||||
},
|
||||
#if SOC_I2C_NUM > 1
|
||||
{&I2C1, 1, -1, -1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
,
|
||||
NULL
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
#if CONFIG_DISABLE_HAL_LOCKS
|
||||
#define I2C_SLAVE_MUTEX_LOCK()
|
||||
#define I2C_SLAVE_MUTEX_UNLOCK()
|
||||
#else
|
||||
#define I2C_SLAVE_MUTEX_LOCK() \
|
||||
if (i2c->lock) { \
|
||||
xSemaphoreTake(i2c->lock, portMAX_DELAY); \
|
||||
}
|
||||
#define I2C_SLAVE_MUTEX_UNLOCK() \
|
||||
if (i2c->lock) { \
|
||||
xSemaphoreGive(i2c->lock); \
|
||||
}
|
||||
#endif
|
||||
|
||||
//-------------------------------------- HAL_LL (Missing Functions) ------------------------------------------------
|
||||
typedef enum {
|
||||
I2C_STRETCH_CAUSE_MASTER_READ,
|
||||
I2C_STRETCH_CAUSE_TX_FIFO_EMPTY,
|
||||
I2C_STRETCH_CAUSE_RX_FIFO_FULL,
|
||||
I2C_STRETCH_CAUSE_MAX
|
||||
} i2c_stretch_cause_t;
|
||||
|
||||
static inline i2c_stretch_cause_t i2c_ll_stretch_cause(i2c_dev_t *hw) {
|
||||
#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
|
||||
return hw->sr.stretch_cause;
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
return hw->status_reg.stretch_cause;
|
||||
#else
|
||||
return I2C_STRETCH_CAUSE_MAX;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void i2c_ll_set_stretch(i2c_dev_t *hw, uint16_t time) {
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32
|
||||
typeof(hw->scl_stretch_conf) scl_stretch_conf;
|
||||
scl_stretch_conf.val = 0;
|
||||
scl_stretch_conf.slave_scl_stretch_en = (time > 0);
|
||||
scl_stretch_conf.stretch_protect_num = time;
|
||||
scl_stretch_conf.slave_scl_stretch_clr = 1;
|
||||
hw->scl_stretch_conf.val = scl_stretch_conf.val;
|
||||
if (time > 0) {
|
||||
//enable interrupt
|
||||
hw->int_ena.val |= I2C_SLAVE_STRETCH_INT_ENA;
|
||||
} else {
|
||||
//disable interrupt
|
||||
hw->int_ena.val &= (~I2C_SLAVE_STRETCH_INT_ENA);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void i2c_ll_stretch_clr(i2c_dev_t *hw) {
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32
|
||||
hw->scl_stretch_conf.slave_scl_stretch_clr = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool i2c_ll_slave_addressed(i2c_dev_t *hw) {
|
||||
#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32H2
|
||||
return hw->sr.slave_addressed;
|
||||
#else
|
||||
return hw->status_reg.slave_addressed;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool i2c_ll_slave_rw(i2c_dev_t *hw) //not exposed by hal_ll
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32H2
|
||||
return hw->sr.slave_rw;
|
||||
#else
|
||||
return hw->status_reg.slave_rw;
|
||||
#endif
|
||||
}
|
||||
|
||||
//-------------------------------------- PRIVATE (Function Prototypes) ------------------------------------------------
|
||||
static void i2c_slave_free_resources(i2c_slave_struct_t *i2c);
|
||||
static void i2c_slave_delay_us(uint64_t us);
|
||||
static void i2c_slave_gpio_mode(int8_t pin, gpio_mode_t mode);
|
||||
static bool i2c_slave_check_line_state(int8_t sda, int8_t scl);
|
||||
static bool i2c_slave_attach_gpio(i2c_slave_struct_t *i2c, int8_t sda, int8_t scl);
|
||||
static bool i2c_slave_detach_gpio(i2c_slave_struct_t *i2c);
|
||||
static bool i2c_slave_set_frequency(i2c_slave_struct_t *i2c, uint32_t clk_speed);
|
||||
static bool i2c_slave_send_event(i2c_slave_struct_t *i2c, i2c_slave_queue_event_t *event);
|
||||
static bool i2c_slave_handle_tx_fifo_empty(i2c_slave_struct_t *i2c);
|
||||
static bool i2c_slave_handle_rx_fifo_full(i2c_slave_struct_t *i2c, uint32_t len);
|
||||
static size_t i2c_slave_read_rx(i2c_slave_struct_t *i2c, uint8_t *data, size_t len);
|
||||
static void i2c_slave_isr_handler(void *arg);
|
||||
static void i2c_slave_task(void *pv_args);
|
||||
static bool i2cSlaveDetachBus(void *bus_i2c_num);
|
||||
|
||||
//=====================================================================================================================
|
||||
//-------------------------------------- Public Functions -------------------------------------------------------------
|
||||
//=====================================================================================================================
|
||||
|
||||
esp_err_t i2cSlaveAttachCallbacks(uint8_t num, i2c_slave_request_cb_t request_callback, i2c_slave_receive_cb_t receive_callback, void *arg) {
|
||||
if (num >= SOC_I2C_NUM) {
|
||||
log_e("Invalid port num: %u", num);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
i2c_slave_struct_t *i2c = &_i2c_bus_array[num];
|
||||
I2C_SLAVE_MUTEX_LOCK();
|
||||
i2c->request_callback = request_callback;
|
||||
i2c->receive_callback = receive_callback;
|
||||
i2c->arg = arg;
|
||||
I2C_SLAVE_MUTEX_UNLOCK();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t i2cSlaveInit(uint8_t num, int sda, int scl, uint16_t slaveID, uint32_t frequency, size_t rx_len, size_t tx_len) {
|
||||
if (num >= SOC_I2C_NUM) {
|
||||
log_e("Invalid port num: %u", num);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (sda < 0 || scl < 0) {
|
||||
log_e("invalid pins sda=%d, scl=%d", sda, scl);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (!frequency) {
|
||||
frequency = 100000;
|
||||
} else if (frequency > 1000000) {
|
||||
frequency = 1000000;
|
||||
}
|
||||
|
||||
perimanSetBusDeinit(ESP32_BUS_TYPE_I2C_SLAVE_SDA, i2cSlaveDetachBus);
|
||||
perimanSetBusDeinit(ESP32_BUS_TYPE_I2C_SLAVE_SCL, i2cSlaveDetachBus);
|
||||
|
||||
if (!perimanClearPinBus(sda) || !perimanClearPinBus(scl)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
log_i("Initializing I2C Slave: sda=%d scl=%d freq=%d, addr=0x%x", sda, scl, frequency, slaveID);
|
||||
|
||||
i2c_slave_struct_t *i2c = &_i2c_bus_array[num];
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
if (!i2c->lock) {
|
||||
i2c->lock = xSemaphoreCreateMutex();
|
||||
if (i2c->lock == NULL) {
|
||||
log_e("RX queue create failed");
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
I2C_SLAVE_MUTEX_LOCK();
|
||||
i2c_slave_free_resources(i2c);
|
||||
|
||||
#if I2C_SLAVE_USE_RX_QUEUE
|
||||
i2c->rx_queue = xQueueCreate(rx_len, sizeof(uint8_t));
|
||||
if (i2c->rx_queue == NULL) {
|
||||
log_e("RX queue create failed");
|
||||
ret = ESP_ERR_NO_MEM;
|
||||
goto fail;
|
||||
}
|
||||
#else
|
||||
i2c->rx_ring_buf = xRingbufferCreate(rx_len, RINGBUF_TYPE_BYTEBUF);
|
||||
if (i2c->rx_ring_buf == NULL) {
|
||||
log_e("RX RingBuf create failed");
|
||||
ret = ESP_ERR_NO_MEM;
|
||||
goto fail;
|
||||
}
|
||||
#endif
|
||||
|
||||
i2c->tx_queue = xQueueCreate(tx_len, sizeof(uint8_t));
|
||||
if (i2c->tx_queue == NULL) {
|
||||
log_e("TX queue create failed");
|
||||
ret = ESP_ERR_NO_MEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
i2c->event_queue = xQueueCreate(16, sizeof(i2c_slave_queue_event_t));
|
||||
if (i2c->event_queue == NULL) {
|
||||
log_e("Event queue create failed");
|
||||
ret = ESP_ERR_NO_MEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
xTaskCreate(i2c_slave_task, "i2c_slave_task", 4096, i2c, 20, &i2c->task_handle);
|
||||
if (i2c->task_handle == NULL) {
|
||||
log_e("Event thread create failed");
|
||||
ret = ESP_ERR_NO_MEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (frequency == 0) {
|
||||
frequency = 100000L;
|
||||
}
|
||||
frequency = (frequency * 5) / 4;
|
||||
|
||||
if (i2c->num == 0) {
|
||||
periph_ll_enable_clk_clear_rst(PERIPH_I2C0_MODULE);
|
||||
#if SOC_I2C_NUM > 1
|
||||
} else {
|
||||
periph_ll_enable_clk_clear_rst(PERIPH_I2C1_MODULE);
|
||||
#endif
|
||||
}
|
||||
|
||||
i2c_ll_slave_init(i2c->dev);
|
||||
i2c_ll_enable_fifo_mode(i2c->dev, true);
|
||||
i2c_ll_set_slave_addr(i2c->dev, slaveID, false);
|
||||
i2c_ll_set_tout(i2c->dev, I2C_LL_MAX_TIMEOUT);
|
||||
i2c_slave_set_frequency(i2c, frequency);
|
||||
|
||||
if (!i2c_slave_check_line_state(sda, scl)) {
|
||||
log_e("bad pin state");
|
||||
ret = ESP_FAIL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
i2c_slave_attach_gpio(i2c, sda, scl);
|
||||
|
||||
if (i2c_ll_is_bus_busy(i2c->dev)) {
|
||||
log_w("Bus busy, reinit");
|
||||
ret = ESP_FAIL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
i2c_ll_disable_intr_mask(i2c->dev, I2C_LL_INTR_MASK);
|
||||
i2c_ll_clear_intr_mask(i2c->dev, I2C_LL_INTR_MASK);
|
||||
i2c_ll_enable_fifo_mode(i2c->dev, true);
|
||||
|
||||
if (!i2c->intr_handle) {
|
||||
uint32_t flags = ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_SHARED;
|
||||
if (i2c->num == 0) {
|
||||
ret = esp_intr_alloc(ETS_I2C_EXT0_INTR_SOURCE, flags, &i2c_slave_isr_handler, i2c, &i2c->intr_handle);
|
||||
#if SOC_I2C_NUM > 1
|
||||
} else {
|
||||
ret = esp_intr_alloc(ETS_I2C_EXT1_INTR_SOURCE, flags, &i2c_slave_isr_handler, i2c, &i2c->intr_handle);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (ret != ESP_OK) {
|
||||
log_e("install interrupt handler Failed=%d", ret);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
i2c_ll_txfifo_rst(i2c->dev);
|
||||
i2c_ll_rxfifo_rst(i2c->dev);
|
||||
i2c_ll_slave_enable_rx_it(i2c->dev);
|
||||
i2c_ll_set_stretch(i2c->dev, 0x3FF);
|
||||
i2c_ll_update(i2c->dev);
|
||||
if (!perimanSetPinBus(sda, ESP32_BUS_TYPE_I2C_SLAVE_SDA, (void *)(i2c->num + 1), i2c->num, -1)
|
||||
|| !perimanSetPinBus(scl, ESP32_BUS_TYPE_I2C_SLAVE_SCL, (void *)(i2c->num + 1), i2c->num, -1)) {
|
||||
i2cSlaveDetachBus((void *)(i2c->num + 1));
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
I2C_SLAVE_MUTEX_UNLOCK();
|
||||
return ret;
|
||||
|
||||
fail:
|
||||
i2c_slave_free_resources(i2c);
|
||||
I2C_SLAVE_MUTEX_UNLOCK();
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t i2cSlaveDeinit(uint8_t num) {
|
||||
if (num >= SOC_I2C_NUM) {
|
||||
log_e("Invalid port num: %u", num);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
i2c_slave_struct_t *i2c = &_i2c_bus_array[num];
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
if (!i2c->lock) {
|
||||
log_e("Lock is not initialized! Did you call i2c_slave_init()?");
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
#endif
|
||||
I2C_SLAVE_MUTEX_LOCK();
|
||||
int scl = i2c->scl;
|
||||
int sda = i2c->sda;
|
||||
i2c_slave_free_resources(i2c);
|
||||
perimanClearPinBus(scl);
|
||||
perimanClearPinBus(sda);
|
||||
I2C_SLAVE_MUTEX_UNLOCK();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
size_t i2cSlaveWrite(uint8_t num, const uint8_t *buf, uint32_t len, uint32_t timeout_ms) {
|
||||
if (num >= SOC_I2C_NUM) {
|
||||
log_e("Invalid port num: %u", num);
|
||||
return 0;
|
||||
}
|
||||
uint32_t to_queue = 0, to_fifo = 0;
|
||||
i2c_slave_struct_t *i2c = &_i2c_bus_array[num];
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
if (!i2c->lock) {
|
||||
log_e("Lock is not initialized! Did you call i2c_slave_init()?");
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
#endif
|
||||
if (!i2c->tx_queue) {
|
||||
return 0;
|
||||
}
|
||||
I2C_SLAVE_MUTEX_LOCK();
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
i2c_ll_slave_disable_tx_it(i2c->dev);
|
||||
uint32_t txfifo_len = 0;
|
||||
i2c_ll_get_txfifo_len(i2c->dev, &txfifo_len);
|
||||
if (txfifo_len < SOC_I2C_FIFO_LEN) {
|
||||
i2c_ll_txfifo_rst(i2c->dev);
|
||||
}
|
||||
#endif
|
||||
i2c_ll_get_txfifo_len(i2c->dev, &to_fifo);
|
||||
if (to_fifo) {
|
||||
if (len < to_fifo) {
|
||||
to_fifo = len;
|
||||
}
|
||||
i2c_ll_write_txfifo(i2c->dev, (uint8_t *)buf, to_fifo);
|
||||
buf += to_fifo;
|
||||
len -= to_fifo;
|
||||
//reset tx_queue
|
||||
xQueueReset(i2c->tx_queue);
|
||||
//write the rest of the bytes to the queue
|
||||
if (len) {
|
||||
to_queue = uxQueueSpacesAvailable(i2c->tx_queue);
|
||||
if (len < to_queue) {
|
||||
to_queue = len;
|
||||
}
|
||||
for (size_t i = 0; i < to_queue; i++) {
|
||||
if (xQueueSend(i2c->tx_queue, &buf[i], timeout_ms / portTICK_PERIOD_MS) != pdTRUE) {
|
||||
xQueueReset(i2c->tx_queue);
|
||||
to_queue = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//no need to enable TX_EMPTY if tx_queue is empty
|
||||
if (to_queue) {
|
||||
i2c_ll_slave_enable_tx_it(i2c->dev);
|
||||
}
|
||||
}
|
||||
}
|
||||
I2C_SLAVE_MUTEX_UNLOCK();
|
||||
return to_queue + to_fifo;
|
||||
}
|
||||
|
||||
//=====================================================================================================================
|
||||
//-------------------------------------- Private Functions ------------------------------------------------------------
|
||||
//=====================================================================================================================
|
||||
|
||||
static void i2c_slave_free_resources(i2c_slave_struct_t *i2c) {
|
||||
i2c_slave_detach_gpio(i2c);
|
||||
i2c_ll_set_slave_addr(i2c->dev, 0, false);
|
||||
i2c_ll_disable_intr_mask(i2c->dev, I2C_LL_INTR_MASK);
|
||||
i2c_ll_clear_intr_mask(i2c->dev, I2C_LL_INTR_MASK);
|
||||
|
||||
if (i2c->intr_handle) {
|
||||
esp_intr_free(i2c->intr_handle);
|
||||
i2c->intr_handle = NULL;
|
||||
}
|
||||
|
||||
if (i2c->task_handle) {
|
||||
vTaskDelete(i2c->task_handle);
|
||||
i2c->task_handle = NULL;
|
||||
}
|
||||
|
||||
#if I2C_SLAVE_USE_RX_QUEUE
|
||||
if (i2c->rx_queue) {
|
||||
vQueueDelete(i2c->rx_queue);
|
||||
i2c->rx_queue = NULL;
|
||||
}
|
||||
#else
|
||||
if (i2c->rx_ring_buf) {
|
||||
vRingbufferDelete(i2c->rx_ring_buf);
|
||||
i2c->rx_ring_buf = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (i2c->tx_queue) {
|
||||
vQueueDelete(i2c->tx_queue);
|
||||
i2c->tx_queue = NULL;
|
||||
}
|
||||
|
||||
if (i2c->event_queue) {
|
||||
vQueueDelete(i2c->event_queue);
|
||||
i2c->event_queue = NULL;
|
||||
}
|
||||
|
||||
i2c->rx_data_count = 0;
|
||||
}
|
||||
|
||||
static bool i2c_slave_set_frequency(i2c_slave_struct_t *i2c, uint32_t clk_speed) {
|
||||
if (i2c == NULL) {
|
||||
log_e("no control buffer");
|
||||
return false;
|
||||
}
|
||||
if (clk_speed > 1100000UL) {
|
||||
clk_speed = 1100000UL;
|
||||
}
|
||||
|
||||
// Adjust Fifo thresholds based on frequency
|
||||
uint32_t a = (clk_speed / 50000L) + 2;
|
||||
log_d("Fifo thresholds: rx_fifo_full = %d, tx_fifo_empty = %d", SOC_I2C_FIFO_LEN - a, a);
|
||||
|
||||
i2c_hal_clk_config_t clk_cal;
|
||||
#if SOC_I2C_SUPPORT_APB
|
||||
i2c_ll_master_cal_bus_clk(APB_CLK_FREQ, clk_speed, &clk_cal);
|
||||
i2c_ll_set_source_clk(i2c->dev, SOC_MOD_CLK_APB); /*!< I2C source clock from APB, 80M*/
|
||||
#elif SOC_I2C_SUPPORT_XTAL
|
||||
i2c_ll_master_cal_bus_clk(XTAL_CLK_FREQ, clk_speed, &clk_cal);
|
||||
i2c_ll_set_source_clk(i2c->dev, SOC_MOD_CLK_XTAL); /*!< I2C source clock from XTAL, 40M */
|
||||
#endif
|
||||
i2c_ll_set_txfifo_empty_thr(i2c->dev, a);
|
||||
i2c_ll_set_rxfifo_full_thr(i2c->dev, SOC_I2C_FIFO_LEN - a);
|
||||
i2c_ll_master_set_bus_timing(i2c->dev, &clk_cal);
|
||||
i2c_ll_master_set_filter(i2c->dev, 3);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void i2c_slave_delay_us(uint64_t us) {
|
||||
uint64_t m = esp_timer_get_time();
|
||||
if (us) {
|
||||
uint64_t e = (m + us);
|
||||
if (m > e) { //overflow
|
||||
while ((uint64_t)esp_timer_get_time() > e);
|
||||
}
|
||||
while ((uint64_t)esp_timer_get_time() < e);
|
||||
}
|
||||
}
|
||||
|
||||
static void i2c_slave_gpio_mode(int8_t pin, gpio_mode_t mode) {
|
||||
gpio_config_t conf = {
|
||||
.pin_bit_mask = 1LL << pin, .mode = mode, .pull_up_en = GPIO_PULLUP_ENABLE, .pull_down_en = GPIO_PULLDOWN_DISABLE, .intr_type = GPIO_INTR_DISABLE
|
||||
};
|
||||
gpio_config(&conf);
|
||||
}
|
||||
|
||||
static bool i2c_slave_check_line_state(int8_t sda, int8_t scl) {
|
||||
if (sda < 0 || scl < 0) {
|
||||
return false; //return false since there is nothing to do
|
||||
}
|
||||
// if the bus is not 'clear' try the cycling SCL until SDA goes High or 9 cycles
|
||||
gpio_set_level(sda, 1);
|
||||
gpio_set_level(scl, 1);
|
||||
i2c_slave_gpio_mode(sda, GPIO_MODE_INPUT | GPIO_MODE_DEF_OD);
|
||||
i2c_slave_gpio_mode(scl, GPIO_MODE_INPUT | GPIO_MODE_DEF_OD);
|
||||
gpio_set_level(scl, 1);
|
||||
|
||||
if (!gpio_get_level(sda) || !gpio_get_level(scl)) { // bus in busy state
|
||||
log_w("invalid state sda(%d)=%d, scl(%d)=%d", sda, gpio_get_level(sda), scl, gpio_get_level(scl));
|
||||
for (uint8_t a = 0; a < 9; a++) {
|
||||
i2c_slave_delay_us(5);
|
||||
if (gpio_get_level(sda) && gpio_get_level(scl)) { // bus recovered
|
||||
log_w("Recovered after %d Cycles", a);
|
||||
gpio_set_level(sda, 0); // start
|
||||
i2c_slave_delay_us(5);
|
||||
for (uint8_t a = 0; a < 9; a++) {
|
||||
gpio_set_level(scl, 1);
|
||||
i2c_slave_delay_us(5);
|
||||
gpio_set_level(scl, 0);
|
||||
i2c_slave_delay_us(5);
|
||||
}
|
||||
gpio_set_level(scl, 1);
|
||||
i2c_slave_delay_us(5);
|
||||
gpio_set_level(sda, 1); // stop
|
||||
break;
|
||||
}
|
||||
gpio_set_level(scl, 0);
|
||||
i2c_slave_delay_us(5);
|
||||
gpio_set_level(scl, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!gpio_get_level(sda) || !gpio_get_level(scl)) { // bus in busy state
|
||||
log_e("Bus Invalid State, Can't init sda=%d, scl=%d", gpio_get_level(sda), gpio_get_level(scl));
|
||||
return false; // bus is busy
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool i2c_slave_attach_gpio(i2c_slave_struct_t *i2c, int8_t sda, int8_t scl) {
|
||||
if (i2c == NULL) {
|
||||
log_e("no control block");
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((sda < 0) || (scl < 0)) {
|
||||
log_e("bad pins sda=%d, scl=%d", sda, scl);
|
||||
return false;
|
||||
}
|
||||
|
||||
i2c->scl = scl;
|
||||
gpio_set_level(scl, 1);
|
||||
i2c_slave_gpio_mode(scl, GPIO_MODE_INPUT_OUTPUT_OD);
|
||||
gpio_matrix_out(scl, I2C_SCL_IDX(i2c->num), false, false);
|
||||
gpio_matrix_in(scl, I2C_SCL_IDX(i2c->num), false);
|
||||
|
||||
i2c->sda = sda;
|
||||
gpio_set_level(sda, 1);
|
||||
i2c_slave_gpio_mode(sda, GPIO_MODE_INPUT_OUTPUT_OD);
|
||||
gpio_matrix_out(sda, I2C_SDA_IDX(i2c->num), false, false);
|
||||
gpio_matrix_in(sda, I2C_SDA_IDX(i2c->num), false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool i2c_slave_detach_gpio(i2c_slave_struct_t *i2c) {
|
||||
if (i2c == NULL) {
|
||||
log_e("no control Block");
|
||||
return false;
|
||||
}
|
||||
if (i2c->scl >= 0) {
|
||||
gpio_matrix_out(i2c->scl, 0x100, false, false);
|
||||
gpio_matrix_in(0x30, I2C_SCL_IDX(i2c->num), false);
|
||||
i2c_slave_gpio_mode(i2c->scl, GPIO_MODE_INPUT);
|
||||
i2c->scl = -1; // un attached
|
||||
}
|
||||
if (i2c->sda >= 0) {
|
||||
gpio_matrix_out(i2c->sda, 0x100, false, false);
|
||||
gpio_matrix_in(0x30, I2C_SDA_IDX(i2c->num), false);
|
||||
i2c_slave_gpio_mode(i2c->sda, GPIO_MODE_INPUT);
|
||||
i2c->sda = -1; // un attached
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool i2c_slave_send_event(i2c_slave_struct_t *i2c, i2c_slave_queue_event_t *event) {
|
||||
bool pxHigherPriorityTaskWoken = false;
|
||||
if (i2c->event_queue) {
|
||||
if (xQueueSendFromISR(i2c->event_queue, event, (BaseType_t *const)&pxHigherPriorityTaskWoken) != pdTRUE) {
|
||||
//log_e("event_queue_full");
|
||||
}
|
||||
}
|
||||
return pxHigherPriorityTaskWoken;
|
||||
}
|
||||
|
||||
static bool i2c_slave_handle_tx_fifo_empty(i2c_slave_struct_t *i2c) {
|
||||
bool pxHigherPriorityTaskWoken = false;
|
||||
uint32_t d = 0, moveCnt = 0;
|
||||
i2c_ll_get_txfifo_len(i2c->dev, &moveCnt);
|
||||
while (moveCnt > 0) { // read tx queue until Fifo is full or queue is empty
|
||||
if (xQueueReceiveFromISR(i2c->tx_queue, &d, (BaseType_t *const)&pxHigherPriorityTaskWoken) == pdTRUE) {
|
||||
i2c_ll_write_txfifo(i2c->dev, (uint8_t *)&d, 1);
|
||||
moveCnt--;
|
||||
} else {
|
||||
i2c_ll_slave_disable_tx_it(i2c->dev);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return pxHigherPriorityTaskWoken;
|
||||
}
|
||||
|
||||
static bool i2c_slave_handle_rx_fifo_full(i2c_slave_struct_t *i2c, uint32_t len) {
|
||||
#if I2C_SLAVE_USE_RX_QUEUE
|
||||
uint32_t d = 0;
|
||||
#else
|
||||
uint8_t data[SOC_I2C_FIFO_LEN];
|
||||
#endif
|
||||
bool pxHigherPriorityTaskWoken = false;
|
||||
#if I2C_SLAVE_USE_RX_QUEUE
|
||||
while (len > 0) {
|
||||
i2c_ll_read_rxfifo(i2c->dev, (uint8_t *)&d, 1);
|
||||
if (xQueueSendFromISR(i2c->rx_queue, &d, (BaseType_t *const)&pxHigherPriorityTaskWoken) != pdTRUE) {
|
||||
log_e("rx_queue_full");
|
||||
} else {
|
||||
i2c->rx_data_count++;
|
||||
}
|
||||
if (--len == 0) {
|
||||
len = i2c_ll_get_rxfifo_cnt(i2c->dev);
|
||||
}
|
||||
#else
|
||||
if (len) {
|
||||
i2c_ll_read_rxfifo(i2c->dev, data, len);
|
||||
if (xRingbufferSendFromISR(i2c->rx_ring_buf, (void *)data, len, (BaseType_t *const)&pxHigherPriorityTaskWoken) != pdTRUE) {
|
||||
log_e("rx_ring_buf_full");
|
||||
} else {
|
||||
i2c->rx_data_count += len;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return pxHigherPriorityTaskWoken;
|
||||
}
|
||||
|
||||
static void i2c_slave_isr_handler(void *arg) {
|
||||
bool pxHigherPriorityTaskWoken = false;
|
||||
i2c_slave_struct_t *i2c = (i2c_slave_struct_t *)arg; // recover data
|
||||
|
||||
uint32_t activeInt = 0;
|
||||
i2c_ll_get_intr_mask(i2c->dev, &activeInt);
|
||||
i2c_ll_clear_intr_mask(i2c->dev, activeInt);
|
||||
uint32_t rx_fifo_len = 0;
|
||||
i2c_ll_get_rxfifo_cnt(i2c->dev, &rx_fifo_len);
|
||||
bool slave_rw = i2c_ll_slave_rw(i2c->dev);
|
||||
|
||||
if (activeInt & I2C_RXFIFO_WM_INT_ENA) { // RX FiFo Full
|
||||
pxHigherPriorityTaskWoken |= i2c_slave_handle_rx_fifo_full(i2c, rx_fifo_len);
|
||||
i2c_ll_slave_enable_rx_it(i2c->dev); //is this necessary?
|
||||
}
|
||||
|
||||
if (activeInt & I2C_TRANS_COMPLETE_INT_ENA) { // STOP
|
||||
if (rx_fifo_len) { //READ RX FIFO
|
||||
pxHigherPriorityTaskWoken |= i2c_slave_handle_rx_fifo_full(i2c, rx_fifo_len);
|
||||
}
|
||||
if (i2c->rx_data_count) { //WRITE or RepeatedStart
|
||||
//SEND RX Event
|
||||
i2c_slave_queue_event_t event;
|
||||
event.event = I2C_SLAVE_EVT_RX;
|
||||
event.stop = !slave_rw;
|
||||
event.param = i2c->rx_data_count;
|
||||
pxHigherPriorityTaskWoken |= i2c_slave_send_event(i2c, &event);
|
||||
//Zero RX count
|
||||
i2c->rx_data_count = 0;
|
||||
}
|
||||
if (slave_rw) { // READ
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
if (i2c->dev->status_reg.scl_main_state_last == 6) {
|
||||
//SEND TX Event
|
||||
i2c_slave_queue_event_t event;
|
||||
event.event = I2C_SLAVE_EVT_TX;
|
||||
pxHigherPriorityTaskWoken |= i2c_slave_send_event(i2c, &event);
|
||||
}
|
||||
#else
|
||||
//reset TX data
|
||||
i2c_ll_txfifo_rst(i2c->dev);
|
||||
uint8_t d;
|
||||
while (xQueueReceiveFromISR(i2c->tx_queue, &d, (BaseType_t *const)&pxHigherPriorityTaskWoken) == pdTRUE); //flush partial write
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32
|
||||
if (activeInt & I2C_SLAVE_STRETCH_INT_ENA) { // STRETCH
|
||||
i2c_stretch_cause_t cause = i2c_ll_stretch_cause(i2c->dev);
|
||||
if (cause == I2C_STRETCH_CAUSE_MASTER_READ) {
|
||||
//on C3 RX data disappears with repeated start, so we need to get it here
|
||||
if (rx_fifo_len) {
|
||||
pxHigherPriorityTaskWoken |= i2c_slave_handle_rx_fifo_full(i2c, rx_fifo_len);
|
||||
}
|
||||
//SEND TX Event
|
||||
i2c_slave_queue_event_t event;
|
||||
event.event = I2C_SLAVE_EVT_TX;
|
||||
pxHigherPriorityTaskWoken |= i2c_slave_send_event(i2c, &event);
|
||||
//will clear after execution
|
||||
} else if (cause == I2C_STRETCH_CAUSE_TX_FIFO_EMPTY) {
|
||||
pxHigherPriorityTaskWoken |= i2c_slave_handle_tx_fifo_empty(i2c);
|
||||
i2c_ll_stretch_clr(i2c->dev);
|
||||
} else if (cause == I2C_STRETCH_CAUSE_RX_FIFO_FULL) {
|
||||
pxHigherPriorityTaskWoken |= i2c_slave_handle_rx_fifo_full(i2c, rx_fifo_len);
|
||||
i2c_ll_stretch_clr(i2c->dev);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (activeInt & I2C_TXFIFO_WM_INT_ENA) { // TX FiFo Empty
|
||||
pxHigherPriorityTaskWoken |= i2c_slave_handle_tx_fifo_empty(i2c);
|
||||
}
|
||||
|
||||
if (pxHigherPriorityTaskWoken) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
}
|
||||
|
||||
static size_t i2c_slave_read_rx(i2c_slave_struct_t *i2c, uint8_t *data, size_t len) {
|
||||
if (!len) {
|
||||
return 0;
|
||||
}
|
||||
#if I2C_SLAVE_USE_RX_QUEUE
|
||||
uint8_t d = 0;
|
||||
BaseType_t res = pdTRUE;
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
if (data) {
|
||||
res = xQueueReceive(i2c->rx_queue, &data[i], 0);
|
||||
} else {
|
||||
res = xQueueReceive(i2c->rx_queue, &d, 0);
|
||||
}
|
||||
if (res != pdTRUE) {
|
||||
log_e("Read Queue(%u) Failed", i);
|
||||
len = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (data) ? len : 0;
|
||||
#else
|
||||
size_t dlen = 0, to_read = len, so_far = 0, available = 0;
|
||||
uint8_t *rx_data = NULL;
|
||||
|
||||
vRingbufferGetInfo(i2c->rx_ring_buf, NULL, NULL, NULL, NULL, &available);
|
||||
if (available < to_read) {
|
||||
log_e("Less available than requested. %u < %u", available, len);
|
||||
to_read = available;
|
||||
}
|
||||
|
||||
while (to_read) {
|
||||
dlen = 0;
|
||||
rx_data = (uint8_t *)xRingbufferReceiveUpTo(i2c->rx_ring_buf, &dlen, 0, to_read);
|
||||
if (!rx_data) {
|
||||
log_e("Receive %u Failed", to_read);
|
||||
return so_far;
|
||||
}
|
||||
if (data) {
|
||||
memcpy(data + so_far, rx_data, dlen);
|
||||
}
|
||||
vRingbufferReturnItem(i2c->rx_ring_buf, rx_data);
|
||||
so_far += dlen;
|
||||
to_read -= dlen;
|
||||
}
|
||||
return (data) ? so_far : 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void i2c_slave_task(void *pv_args) {
|
||||
i2c_slave_struct_t *i2c = (i2c_slave_struct_t *)pv_args;
|
||||
i2c_slave_queue_event_t event;
|
||||
size_t len = 0;
|
||||
bool stop = false;
|
||||
uint8_t *data = NULL;
|
||||
for (;;) {
|
||||
if (xQueueReceive(i2c->event_queue, &event, portMAX_DELAY) == pdTRUE) {
|
||||
// Write
|
||||
if (event.event == I2C_SLAVE_EVT_RX) {
|
||||
len = event.param;
|
||||
stop = event.stop;
|
||||
data = (len > 0) ? (uint8_t *)malloc(len) : NULL;
|
||||
|
||||
if (len && data == NULL) {
|
||||
log_e("Malloc (%u) Failed", len);
|
||||
}
|
||||
len = i2c_slave_read_rx(i2c, data, len);
|
||||
if (i2c->receive_callback) {
|
||||
i2c->receive_callback(i2c->num, data, len, stop, i2c->arg);
|
||||
}
|
||||
free(data);
|
||||
|
||||
// Read
|
||||
} else if (event.event == I2C_SLAVE_EVT_TX) {
|
||||
if (i2c->request_callback) {
|
||||
i2c->request_callback(i2c->num, i2c->arg);
|
||||
}
|
||||
i2c_ll_stretch_clr(i2c->dev);
|
||||
}
|
||||
}
|
||||
}
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
static bool i2cSlaveDetachBus(void *bus_i2c_num) {
|
||||
uint8_t num = (int)bus_i2c_num - 1;
|
||||
i2c_slave_struct_t *i2c = &_i2c_bus_array[num];
|
||||
if (i2c->scl == -1 && i2c->sda == -1) {
|
||||
return true;
|
||||
}
|
||||
esp_err_t err = i2cSlaveDeinit(num);
|
||||
if (err != ESP_OK) {
|
||||
log_e("i2cSlaveDeinit failed with error: %d", err);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif /* SOC_I2C_SUPPORT_SLAVE */
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// 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.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "soc/soc_caps.h"
|
||||
#if SOC_I2C_SUPPORT_SLAVE
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "stdint.h"
|
||||
#include "stddef.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
typedef void (*i2c_slave_request_cb_t)(uint8_t num, void *arg);
|
||||
typedef void (*i2c_slave_receive_cb_t)(uint8_t num, uint8_t *data, size_t len, bool stop, void *arg);
|
||||
esp_err_t i2cSlaveAttachCallbacks(uint8_t num, i2c_slave_request_cb_t request_callback, i2c_slave_receive_cb_t receive_callback, void *arg);
|
||||
|
||||
esp_err_t i2cSlaveInit(uint8_t num, int sda, int scl, uint16_t slaveID, uint32_t frequency, size_t rx_len, size_t tx_len);
|
||||
esp_err_t i2cSlaveDeinit(uint8_t num);
|
||||
size_t i2cSlaveWrite(uint8_t num, const uint8_t *buf, uint32_t len, uint32_t timeout_ms);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SOC_I2C_SUPPORT_SLAVE */
|
||||
|
|
@ -1,409 +0,0 @@
|
|||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// 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.
|
||||
|
||||
#include "esp32-hal-i2c.h"
|
||||
|
||||
#if SOC_I2C_SUPPORTED
|
||||
#include "esp32-hal.h"
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#endif
|
||||
#include "esp_attr.h"
|
||||
#include "esp_system.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "soc/i2c_periph.h"
|
||||
#include "hal/i2c_hal.h"
|
||||
#include "hal/i2c_ll.h"
|
||||
#include "driver/i2c.h"
|
||||
#include "esp32-hal-periman.h"
|
||||
|
||||
#if SOC_I2C_SUPPORT_APB || SOC_I2C_SUPPORT_XTAL
|
||||
#include "esp_private/esp_clk.h"
|
||||
#endif
|
||||
#if SOC_I2C_SUPPORT_RTC
|
||||
#include "clk_ctrl_os.h"
|
||||
#endif
|
||||
|
||||
typedef volatile struct {
|
||||
bool initialized;
|
||||
uint32_t frequency;
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
SemaphoreHandle_t lock;
|
||||
#endif
|
||||
int8_t scl;
|
||||
int8_t sda;
|
||||
|
||||
} i2c_bus_t;
|
||||
|
||||
static i2c_bus_t bus[SOC_I2C_NUM];
|
||||
|
||||
static bool i2cDetachBus(void *bus_i2c_num) {
|
||||
uint8_t i2c_num = (int)bus_i2c_num - 1;
|
||||
if (!bus[i2c_num].initialized) {
|
||||
return true;
|
||||
}
|
||||
esp_err_t err = i2cDeinit(i2c_num);
|
||||
if (err != ESP_OK) {
|
||||
log_e("i2cDeinit failed with error: %d", err);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool i2cIsInit(uint8_t i2c_num) {
|
||||
if (i2c_num >= SOC_I2C_NUM) {
|
||||
return false;
|
||||
}
|
||||
return bus[i2c_num].initialized;
|
||||
}
|
||||
|
||||
esp_err_t i2cInit(uint8_t i2c_num, int8_t sda, int8_t scl, uint32_t frequency) {
|
||||
if (i2c_num >= SOC_I2C_NUM) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
if (bus[i2c_num].lock == NULL) {
|
||||
bus[i2c_num].lock = xSemaphoreCreateMutex();
|
||||
if (bus[i2c_num].lock == NULL) {
|
||||
log_e("xSemaphoreCreateMutex failed");
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
}
|
||||
//acquire lock
|
||||
if (xSemaphoreTake(bus[i2c_num].lock, portMAX_DELAY) != pdTRUE) {
|
||||
log_e("could not acquire lock");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
#endif
|
||||
if (bus[i2c_num].initialized) {
|
||||
log_e("bus is already initialized");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (!frequency) {
|
||||
frequency = 100000UL;
|
||||
} else if (frequency > 1000000UL) {
|
||||
frequency = 1000000UL;
|
||||
}
|
||||
|
||||
perimanSetBusDeinit(ESP32_BUS_TYPE_I2C_MASTER_SDA, i2cDetachBus);
|
||||
perimanSetBusDeinit(ESP32_BUS_TYPE_I2C_MASTER_SCL, i2cDetachBus);
|
||||
|
||||
if (!perimanClearPinBus(sda) || !perimanClearPinBus(scl)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
log_i("Initializing I2C Master: sda=%d scl=%d freq=%d", sda, scl, frequency);
|
||||
|
||||
i2c_config_t conf = {};
|
||||
conf.mode = I2C_MODE_MASTER;
|
||||
conf.scl_io_num = (gpio_num_t)scl;
|
||||
conf.sda_io_num = (gpio_num_t)sda;
|
||||
conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
|
||||
conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
|
||||
conf.master.clk_speed = frequency;
|
||||
conf.clk_flags = I2C_SCLK_SRC_FLAG_FOR_NOMAL; //Any one clock source that is available for the specified frequency may be chosen
|
||||
|
||||
esp_err_t ret = i2c_param_config((i2c_port_t)i2c_num, &conf);
|
||||
if (ret != ESP_OK) {
|
||||
log_e("i2c_param_config failed");
|
||||
} else {
|
||||
ret = i2c_driver_install((i2c_port_t)i2c_num, conf.mode, 0, 0, 0);
|
||||
if (ret != ESP_OK) {
|
||||
log_e("i2c_driver_install failed");
|
||||
} else {
|
||||
bus[i2c_num].initialized = true;
|
||||
bus[i2c_num].frequency = frequency;
|
||||
bus[i2c_num].scl = scl;
|
||||
bus[i2c_num].sda = sda;
|
||||
//Clock Stretching Timeout: 20b:esp32, 5b:esp32-c3, 24b:esp32-s2
|
||||
i2c_set_timeout((i2c_port_t)i2c_num, I2C_LL_MAX_TIMEOUT);
|
||||
if (!perimanSetPinBus(sda, ESP32_BUS_TYPE_I2C_MASTER_SDA, (void *)(i2c_num + 1), i2c_num, -1)
|
||||
|| !perimanSetPinBus(scl, ESP32_BUS_TYPE_I2C_MASTER_SCL, (void *)(i2c_num + 1), i2c_num, -1)) {
|
||||
i2cDetachBus((void *)(i2c_num + 1));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
//release lock
|
||||
xSemaphoreGive(bus[i2c_num].lock);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t i2cDeinit(uint8_t i2c_num) {
|
||||
esp_err_t err = ESP_FAIL;
|
||||
if (i2c_num >= SOC_I2C_NUM) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
//acquire lock
|
||||
if (bus[i2c_num].lock == NULL || xSemaphoreTake(bus[i2c_num].lock, portMAX_DELAY) != pdTRUE) {
|
||||
log_e("could not acquire lock");
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
if (!bus[i2c_num].initialized) {
|
||||
log_e("bus is not initialized");
|
||||
} else {
|
||||
err = i2c_driver_delete((i2c_port_t)i2c_num);
|
||||
if (err == ESP_OK) {
|
||||
bus[i2c_num].initialized = false;
|
||||
perimanClearPinBus(bus[i2c_num].scl);
|
||||
perimanClearPinBus(bus[i2c_num].sda);
|
||||
bus[i2c_num].scl = -1;
|
||||
bus[i2c_num].sda = -1;
|
||||
}
|
||||
}
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
//release lock
|
||||
xSemaphoreGive(bus[i2c_num].lock);
|
||||
#endif
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_err_t i2cWrite(uint8_t i2c_num, uint16_t address, const uint8_t *buff, size_t size, uint32_t timeOutMillis) {
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
i2c_cmd_handle_t cmd = NULL;
|
||||
if (i2c_num >= SOC_I2C_NUM) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
//acquire lock
|
||||
if (bus[i2c_num].lock == NULL || xSemaphoreTake(bus[i2c_num].lock, portMAX_DELAY) != pdTRUE) {
|
||||
log_e("could not acquire lock");
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
if (!bus[i2c_num].initialized) {
|
||||
log_e("bus is not initialized");
|
||||
goto end;
|
||||
}
|
||||
|
||||
//short implementation does not support zero size writes (example when scanning) PR in IDF?
|
||||
//ret = i2c_master_write_to_device((i2c_port_t)i2c_num, address, buff, size, timeOutMillis / portTICK_PERIOD_MS);
|
||||
|
||||
ret = ESP_OK;
|
||||
uint8_t cmd_buff[I2C_LINK_RECOMMENDED_SIZE(1)] = {0};
|
||||
cmd = i2c_cmd_link_create_static(cmd_buff, I2C_LINK_RECOMMENDED_SIZE(1));
|
||||
ret = i2c_master_start(cmd);
|
||||
if (ret != ESP_OK) {
|
||||
goto end;
|
||||
}
|
||||
ret = i2c_master_write_byte(cmd, (address << 1) | I2C_MASTER_WRITE, true);
|
||||
if (ret != ESP_OK) {
|
||||
goto end;
|
||||
}
|
||||
if (size) {
|
||||
ret = i2c_master_write(cmd, buff, size, true);
|
||||
if (ret != ESP_OK) {
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
ret = i2c_master_stop(cmd);
|
||||
if (ret != ESP_OK) {
|
||||
goto end;
|
||||
}
|
||||
ret = i2c_master_cmd_begin((i2c_port_t)i2c_num, cmd, timeOutMillis / portTICK_PERIOD_MS);
|
||||
|
||||
end:
|
||||
if (cmd != NULL) {
|
||||
i2c_cmd_link_delete_static(cmd);
|
||||
}
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
//release lock
|
||||
xSemaphoreGive(bus[i2c_num].lock);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t i2cRead(uint8_t i2c_num, uint16_t address, uint8_t *buff, size_t size, uint32_t timeOutMillis, size_t *readCount) {
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
if (i2c_num >= SOC_I2C_NUM) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
//acquire lock
|
||||
if (bus[i2c_num].lock == NULL || xSemaphoreTake(bus[i2c_num].lock, portMAX_DELAY) != pdTRUE) {
|
||||
log_e("could not acquire lock");
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
if (!bus[i2c_num].initialized) {
|
||||
log_e("bus is not initialized");
|
||||
} else {
|
||||
ret = i2c_master_read_from_device((i2c_port_t)i2c_num, address, buff, size, timeOutMillis / portTICK_PERIOD_MS);
|
||||
if (ret == ESP_OK) {
|
||||
*readCount = size;
|
||||
} else {
|
||||
*readCount = 0;
|
||||
}
|
||||
}
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
//release lock
|
||||
xSemaphoreGive(bus[i2c_num].lock);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t i2cWriteReadNonStop(
|
||||
uint8_t i2c_num, uint16_t address, const uint8_t *wbuff, size_t wsize, uint8_t *rbuff, size_t rsize, uint32_t timeOutMillis, size_t *readCount
|
||||
) {
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
if (i2c_num >= SOC_I2C_NUM) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
//acquire lock
|
||||
if (bus[i2c_num].lock == NULL || xSemaphoreTake(bus[i2c_num].lock, portMAX_DELAY) != pdTRUE) {
|
||||
log_e("could not acquire lock");
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
if (!bus[i2c_num].initialized) {
|
||||
log_e("bus is not initialized");
|
||||
} else {
|
||||
ret = i2c_master_write_read_device((i2c_port_t)i2c_num, address, wbuff, wsize, rbuff, rsize, timeOutMillis / portTICK_PERIOD_MS);
|
||||
if (ret == ESP_OK) {
|
||||
*readCount = rsize;
|
||||
} else {
|
||||
*readCount = 0;
|
||||
}
|
||||
}
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
//release lock
|
||||
xSemaphoreGive(bus[i2c_num].lock);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t i2cSetClock(uint8_t i2c_num, uint32_t frequency) {
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
if (i2c_num >= SOC_I2C_NUM) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
//acquire lock
|
||||
if (bus[i2c_num].lock == NULL || xSemaphoreTake(bus[i2c_num].lock, portMAX_DELAY) != pdTRUE) {
|
||||
log_e("could not acquire lock");
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
if (!bus[i2c_num].initialized) {
|
||||
log_e("bus is not initialized");
|
||||
goto end;
|
||||
}
|
||||
if (bus[i2c_num].frequency == frequency) {
|
||||
ret = ESP_OK;
|
||||
goto end;
|
||||
}
|
||||
if (!frequency) {
|
||||
frequency = 100000UL;
|
||||
} else if (frequency > 1000000UL) {
|
||||
frequency = 1000000UL;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
soc_module_clk_t clk; /*!< I2C source clock */
|
||||
uint32_t clk_freq; /*!< I2C source clock frequency */
|
||||
} i2c_clk_alloc_t;
|
||||
|
||||
typedef enum {
|
||||
I2C_SCLK_DEFAULT = 0, /*!< I2C source clock not selected*/
|
||||
#if SOC_I2C_SUPPORT_APB
|
||||
I2C_SCLK_APB, /*!< I2C source clock from APB, 80M*/
|
||||
#endif
|
||||
#if SOC_I2C_SUPPORT_XTAL
|
||||
I2C_SCLK_XTAL, /*!< I2C source clock from XTAL, 40M */
|
||||
#endif
|
||||
#if SOC_I2C_SUPPORT_RTC
|
||||
I2C_SCLK_RTC, /*!< I2C source clock from 8M RTC, 8M */
|
||||
#endif
|
||||
#if SOC_I2C_SUPPORT_REF_TICK
|
||||
I2C_SCLK_REF_TICK, /*!< I2C source clock from REF_TICK, 1M */
|
||||
#endif
|
||||
I2C_SCLK_MAX,
|
||||
} i2c_sclk_t;
|
||||
|
||||
// i2c clock characteristic, The order is the same as i2c_sclk_t.
|
||||
i2c_clk_alloc_t i2c_clk_alloc[I2C_SCLK_MAX] = {
|
||||
{0, 0},
|
||||
#if SOC_I2C_SUPPORT_APB
|
||||
{SOC_MOD_CLK_APB, esp_clk_apb_freq()}, /*!< I2C APB clock characteristic*/
|
||||
#endif
|
||||
#if SOC_I2C_SUPPORT_XTAL
|
||||
{SOC_MOD_CLK_XTAL, esp_clk_xtal_freq()}, /*!< I2C XTAL characteristic*/
|
||||
#endif
|
||||
#if SOC_I2C_SUPPORT_RTC
|
||||
{SOC_MOD_CLK_RC_FAST, periph_rtc_dig_clk8m_get_freq()}, /*!< I2C 20M RTC characteristic*/
|
||||
#endif
|
||||
#if SOC_I2C_SUPPORT_REF_TICK
|
||||
{SOC_MOD_CLK_REF_TICK, REF_CLK_FREQ}, /*!< I2C REF_TICK characteristic*/
|
||||
#endif
|
||||
};
|
||||
|
||||
i2c_sclk_t src_clk = I2C_SCLK_DEFAULT;
|
||||
ret = ESP_OK;
|
||||
for (i2c_sclk_t clk = I2C_SCLK_DEFAULT + 1; clk < I2C_SCLK_MAX; clk++) {
|
||||
#if CONFIG_IDF_TARGET_ESP32S3
|
||||
if (clk == I2C_SCLK_RTC) { // RTC clock for s3 is inaccessible now.
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
if (frequency <= i2c_clk_alloc[clk].clk_freq) {
|
||||
src_clk = clk;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (src_clk == I2C_SCLK_DEFAULT || src_clk == I2C_SCLK_MAX) {
|
||||
log_e("clock source could not be selected");
|
||||
ret = ESP_FAIL;
|
||||
} else {
|
||||
i2c_hal_context_t hal;
|
||||
hal.dev = I2C_LL_GET_HW(i2c_num);
|
||||
#if SOC_I2C_SUPPORT_RTC
|
||||
if (src_clk == I2C_SCLK_RTC) {
|
||||
periph_rtc_dig_clk8m_enable();
|
||||
}
|
||||
#endif
|
||||
i2c_hal_set_bus_timing(&(hal), frequency, i2c_clk_alloc[src_clk].clk, i2c_clk_alloc[src_clk].clk_freq);
|
||||
bus[i2c_num].frequency = frequency;
|
||||
//Clock Stretching Timeout: 20b:esp32, 5b:esp32-c3, 24b:esp32-s2
|
||||
i2c_set_timeout((i2c_port_t)i2c_num, I2C_LL_MAX_TIMEOUT);
|
||||
}
|
||||
|
||||
end:
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
//release lock
|
||||
xSemaphoreGive(bus[i2c_num].lock);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t i2cGetClock(uint8_t i2c_num, uint32_t *frequency) {
|
||||
if (i2c_num >= SOC_I2C_NUM) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (!bus[i2c_num].initialized) {
|
||||
log_e("bus is not initialized");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
*frequency = bus[i2c_num].frequency;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#endif /* SOC_I2C_SUPPORTED */
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// 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.
|
||||
// modified Nov 2017 by Chuck Todd <StickBreaker> to support Interrupt Driven I/O
|
||||
// modified Nov 2021 by Hristo Gochkov <Me-No-Dev> to support ESP-IDF API
|
||||
|
||||
#ifndef _ESP32_HAL_I2C_H_
|
||||
#define _ESP32_HAL_I2C_H_
|
||||
|
||||
#include "soc/soc_caps.h"
|
||||
#if SOC_I2C_SUPPORTED
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <esp_err.h>
|
||||
|
||||
esp_err_t i2cInit(uint8_t i2c_num, int8_t sda, int8_t scl, uint32_t clk_speed);
|
||||
esp_err_t i2cDeinit(uint8_t i2c_num);
|
||||
esp_err_t i2cSetClock(uint8_t i2c_num, uint32_t frequency);
|
||||
esp_err_t i2cGetClock(uint8_t i2c_num, uint32_t *frequency);
|
||||
esp_err_t i2cWrite(uint8_t i2c_num, uint16_t address, const uint8_t *buff, size_t size, uint32_t timeOutMillis);
|
||||
esp_err_t i2cRead(uint8_t i2c_num, uint16_t address, uint8_t *buff, size_t size, uint32_t timeOutMillis, size_t *readCount);
|
||||
esp_err_t i2cWriteReadNonStop(
|
||||
uint8_t i2c_num, uint16_t address, const uint8_t *wbuff, size_t wsize, uint8_t *rbuff, size_t rsize, uint32_t timeOutMillis, size_t *readCount
|
||||
);
|
||||
bool i2cIsInit(uint8_t i2c_num);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SOC_I2C_SUPPORTED */
|
||||
#endif /* _ESP32_HAL_I2C_H_ */
|
||||
|
|
@ -1,449 +0,0 @@
|
|||
// Copyright 2015-2023 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// 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.
|
||||
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#if SOC_LEDC_SUPPORTED
|
||||
#include "esp32-hal.h"
|
||||
#include "esp32-hal-ledc.h"
|
||||
#include "driver/ledc.h"
|
||||
#include "esp32-hal-periman.h"
|
||||
#include "soc/gpio_sig_map.h"
|
||||
#include "esp_rom_gpio.h"
|
||||
#include "hal/ledc_ll.h"
|
||||
|
||||
#ifdef SOC_LEDC_SUPPORT_HS_MODE
|
||||
#define LEDC_CHANNELS (SOC_LEDC_CHANNEL_NUM << 1)
|
||||
#else
|
||||
#define LEDC_CHANNELS (SOC_LEDC_CHANNEL_NUM)
|
||||
#endif
|
||||
|
||||
//Use XTAL clock if possible to avoid timer frequency error when setting APB clock < 80 Mhz
|
||||
//Need to be fixed in ESP-IDF
|
||||
#ifdef SOC_LEDC_SUPPORT_XTAL_CLOCK
|
||||
#define LEDC_DEFAULT_CLK LEDC_USE_XTAL_CLK
|
||||
#else
|
||||
#define LEDC_DEFAULT_CLK LEDC_AUTO_CLK
|
||||
#endif
|
||||
|
||||
#define LEDC_MAX_BIT_WIDTH SOC_LEDC_TIMER_BIT_WIDTH
|
||||
|
||||
typedef struct {
|
||||
int used_channels : LEDC_CHANNELS; // Used channels as a bits
|
||||
} ledc_periph_t;
|
||||
|
||||
ledc_periph_t ledc_handle = {0};
|
||||
|
||||
static bool fade_initialized = false;
|
||||
|
||||
static bool ledcDetachBus(void *bus) {
|
||||
ledc_channel_handle_t *handle = (ledc_channel_handle_t *)bus;
|
||||
bool channel_found = false;
|
||||
// Check if more pins are attached to the same ledc channel
|
||||
for (uint8_t i = 0; i < SOC_GPIO_PIN_COUNT; i++) {
|
||||
if (!perimanPinIsValid(i) || i == handle->pin) {
|
||||
continue; //invalid pin or same pin
|
||||
}
|
||||
peripheral_bus_type_t type = perimanGetPinBusType(i);
|
||||
if (type == ESP32_BUS_TYPE_LEDC) {
|
||||
ledc_channel_handle_t *bus_check = (ledc_channel_handle_t *)perimanGetPinBus(i, ESP32_BUS_TYPE_LEDC);
|
||||
if (bus_check->channel == handle->channel) {
|
||||
channel_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
pinMatrixOutDetach(handle->pin, false, false);
|
||||
if (!channel_found) {
|
||||
ledc_handle.used_channels &= ~(1UL << handle->channel);
|
||||
}
|
||||
free(handle);
|
||||
if (ledc_handle.used_channels == 0) {
|
||||
ledc_fade_func_uninstall();
|
||||
fade_initialized = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ledcAttachChannel(uint8_t pin, uint32_t freq, uint8_t resolution, uint8_t channel) {
|
||||
if (channel >= LEDC_CHANNELS) {
|
||||
log_e("Channel %u is not available (maximum %u)!", channel, LEDC_CHANNELS);
|
||||
return false;
|
||||
}
|
||||
if (freq == 0) {
|
||||
log_e("LEDC pin %u - frequency can't be zero.", pin);
|
||||
return false;
|
||||
}
|
||||
if (resolution == 0 || resolution > LEDC_MAX_BIT_WIDTH) {
|
||||
log_e("LEDC pin %u - resolution is zero or it is too big (maximum %u)", pin, LEDC_MAX_BIT_WIDTH);
|
||||
return false;
|
||||
}
|
||||
|
||||
perimanSetBusDeinit(ESP32_BUS_TYPE_LEDC, ledcDetachBus);
|
||||
ledc_channel_handle_t *bus = (ledc_channel_handle_t *)perimanGetPinBus(pin, ESP32_BUS_TYPE_LEDC);
|
||||
if (bus != NULL) {
|
||||
log_e("Pin %u is already attached to LEDC (channel %u, resolution %u)", pin, bus->channel, bus->channel_resolution);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!perimanClearPinBus(pin)) {
|
||||
log_e("Pin %u is already attached to another bus and failed to detach", pin);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t group = (channel / 8), timer = ((channel / 2) % 4);
|
||||
bool channel_used = ledc_handle.used_channels & (1UL << channel);
|
||||
if (channel_used) {
|
||||
log_i("Channel %u is already set up, given frequency and resolution will be ignored", channel);
|
||||
if (ledc_set_pin(pin, group, channel % 8) != ESP_OK) {
|
||||
log_e("Attaching pin to already used channel failed!");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
ledc_timer_config_t ledc_timer = {.speed_mode = group, .timer_num = timer, .duty_resolution = resolution, .freq_hz = freq, .clk_cfg = LEDC_DEFAULT_CLK};
|
||||
if (ledc_timer_config(&ledc_timer) != ESP_OK) {
|
||||
log_e("ledc setup failed!");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t duty = ledc_get_duty(group, (channel % 8));
|
||||
|
||||
ledc_channel_config_t ledc_channel = {
|
||||
.speed_mode = group, .channel = (channel % 8), .timer_sel = timer, .intr_type = LEDC_INTR_DISABLE, .gpio_num = pin, .duty = duty, .hpoint = 0
|
||||
};
|
||||
ledc_channel_config(&ledc_channel);
|
||||
}
|
||||
|
||||
ledc_channel_handle_t *handle = (ledc_channel_handle_t *)malloc(sizeof(ledc_channel_handle_t));
|
||||
handle->pin = pin;
|
||||
handle->channel = channel;
|
||||
#ifndef SOC_LEDC_SUPPORT_FADE_STOP
|
||||
handle->lock = NULL;
|
||||
#endif
|
||||
|
||||
//get resolution of selected channel when used
|
||||
if (channel_used) {
|
||||
uint32_t channel_resolution = 0;
|
||||
ledc_ll_get_duty_resolution(LEDC_LL_GET_HW(), group, timer, &channel_resolution);
|
||||
log_i("Channel %u frequency: %u, resolution: %u", channel, ledc_get_freq(group, timer), channel_resolution);
|
||||
handle->channel_resolution = (uint8_t)channel_resolution;
|
||||
} else {
|
||||
handle->channel_resolution = resolution;
|
||||
ledc_handle.used_channels |= 1UL << channel;
|
||||
}
|
||||
|
||||
if (!perimanSetPinBus(pin, ESP32_BUS_TYPE_LEDC, (void *)handle, group, channel)) {
|
||||
ledcDetachBus((void *)handle);
|
||||
return false;
|
||||
}
|
||||
|
||||
log_i("LEDC attached to pin %u (channel %u, resolution %u)", pin, channel, resolution);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ledcAttach(uint8_t pin, uint32_t freq, uint8_t resolution) {
|
||||
int free_channel = ~ledc_handle.used_channels & (ledc_handle.used_channels + 1);
|
||||
if (free_channel == 0) {
|
||||
log_e("No more LEDC channels available! (maximum is %u channels)", LEDC_CHANNELS);
|
||||
return false;
|
||||
}
|
||||
uint8_t channel = __builtin_ctz(free_channel); // Convert the free_channel bit to channel number
|
||||
|
||||
return ledcAttachChannel(pin, freq, resolution, channel);
|
||||
}
|
||||
|
||||
bool ledcWrite(uint8_t pin, uint32_t duty) {
|
||||
ledc_channel_handle_t *bus = (ledc_channel_handle_t *)perimanGetPinBus(pin, ESP32_BUS_TYPE_LEDC);
|
||||
if (bus != NULL) {
|
||||
|
||||
uint8_t group = (bus->channel / 8), channel = (bus->channel % 8);
|
||||
|
||||
//Fixing if all bits in resolution is set = LEDC FULL ON
|
||||
uint32_t max_duty = (1 << bus->channel_resolution) - 1;
|
||||
|
||||
if ((duty == max_duty) && (max_duty != 1)) {
|
||||
duty = max_duty + 1;
|
||||
}
|
||||
|
||||
ledc_set_duty(group, channel, duty);
|
||||
ledc_update_duty(group, channel);
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ledcWriteChannel(uint8_t channel, uint32_t duty) {
|
||||
//check if channel is valid and used
|
||||
if (channel >= LEDC_CHANNELS || !(ledc_handle.used_channels & (1UL << channel))) {
|
||||
log_e("Channel %u is not available (maximum %u) or not used!", channel, LEDC_CHANNELS);
|
||||
return false;
|
||||
}
|
||||
uint8_t group = (channel / 8), timer = ((channel / 2) % 4);
|
||||
|
||||
//Fixing if all bits in resolution is set = LEDC FULL ON
|
||||
uint32_t resolution = 0;
|
||||
ledc_ll_get_duty_resolution(LEDC_LL_GET_HW(), group, timer, &resolution);
|
||||
|
||||
uint32_t max_duty = (1 << resolution) - 1;
|
||||
|
||||
if ((duty == max_duty) && (max_duty != 1)) {
|
||||
duty = max_duty + 1;
|
||||
}
|
||||
|
||||
ledc_set_duty(group, channel, duty);
|
||||
ledc_update_duty(group, channel);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t ledcRead(uint8_t pin) {
|
||||
ledc_channel_handle_t *bus = (ledc_channel_handle_t *)perimanGetPinBus(pin, ESP32_BUS_TYPE_LEDC);
|
||||
if (bus != NULL) {
|
||||
|
||||
uint8_t group = (bus->channel / 8), channel = (bus->channel % 8);
|
||||
return ledc_get_duty(group, channel);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t ledcReadFreq(uint8_t pin) {
|
||||
ledc_channel_handle_t *bus = (ledc_channel_handle_t *)perimanGetPinBus(pin, ESP32_BUS_TYPE_LEDC);
|
||||
if (bus != NULL) {
|
||||
if (!ledcRead(pin)) {
|
||||
return 0;
|
||||
}
|
||||
uint8_t group = (bus->channel / 8), timer = ((bus->channel / 2) % 4);
|
||||
return ledc_get_freq(group, timer);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t ledcWriteTone(uint8_t pin, uint32_t freq) {
|
||||
ledc_channel_handle_t *bus = (ledc_channel_handle_t *)perimanGetPinBus(pin, ESP32_BUS_TYPE_LEDC);
|
||||
if (bus != NULL) {
|
||||
|
||||
if (!freq) {
|
||||
ledcWrite(pin, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t group = (bus->channel / 8), timer = ((bus->channel / 2) % 4);
|
||||
|
||||
ledc_timer_config_t ledc_timer = {.speed_mode = group, .timer_num = timer, .duty_resolution = 10, .freq_hz = freq, .clk_cfg = LEDC_DEFAULT_CLK};
|
||||
|
||||
if (ledc_timer_config(&ledc_timer) != ESP_OK) {
|
||||
log_e("ledcWriteTone configuration failed!");
|
||||
return 0;
|
||||
}
|
||||
bus->channel_resolution = 10;
|
||||
|
||||
uint32_t res_freq = ledc_get_freq(group, timer);
|
||||
ledcWrite(pin, 0x1FF);
|
||||
return res_freq;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t ledcWriteNote(uint8_t pin, note_t note, uint8_t octave) {
|
||||
const uint16_t noteFrequencyBase[12] = {// C C# D Eb E F F# G G# A Bb B
|
||||
4186, 4435, 4699, 4978, 5274, 5588, 5920, 6272, 6645, 7040, 7459, 7902
|
||||
};
|
||||
|
||||
if (octave > 8 || note >= NOTE_MAX) {
|
||||
return 0;
|
||||
}
|
||||
uint32_t noteFreq = (uint32_t)noteFrequencyBase[note] / (uint32_t)(1 << (8 - octave));
|
||||
return ledcWriteTone(pin, noteFreq);
|
||||
}
|
||||
|
||||
bool ledcDetach(uint8_t pin) {
|
||||
ledc_channel_handle_t *bus = (ledc_channel_handle_t *)perimanGetPinBus(pin, ESP32_BUS_TYPE_LEDC);
|
||||
if (bus != NULL) {
|
||||
// will call ledcDetachBus
|
||||
return perimanClearPinBus(pin);
|
||||
} else {
|
||||
log_e("pin %u is not attached to LEDC", pin);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t ledcChangeFrequency(uint8_t pin, uint32_t freq, uint8_t resolution) {
|
||||
ledc_channel_handle_t *bus = (ledc_channel_handle_t *)perimanGetPinBus(pin, ESP32_BUS_TYPE_LEDC);
|
||||
if (bus != NULL) {
|
||||
if (freq == 0) {
|
||||
log_e("LEDC pin %u - frequency can't be zero.", pin);
|
||||
return 0;
|
||||
}
|
||||
if (resolution == 0 || resolution > LEDC_MAX_BIT_WIDTH) {
|
||||
log_e("LEDC pin %u - resolution is zero or it is too big (maximum %u)", pin, LEDC_MAX_BIT_WIDTH);
|
||||
return 0;
|
||||
}
|
||||
uint8_t group = (bus->channel / 8), timer = ((bus->channel / 2) % 4);
|
||||
|
||||
ledc_timer_config_t ledc_timer = {.speed_mode = group, .timer_num = timer, .duty_resolution = resolution, .freq_hz = freq, .clk_cfg = LEDC_DEFAULT_CLK};
|
||||
|
||||
if (ledc_timer_config(&ledc_timer) != ESP_OK) {
|
||||
log_e("ledcChangeFrequency failed!");
|
||||
return 0;
|
||||
}
|
||||
bus->channel_resolution = resolution;
|
||||
return ledc_get_freq(group, timer);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool ledcOutputInvert(uint8_t pin, bool out_invert) {
|
||||
ledc_channel_handle_t *bus = (ledc_channel_handle_t *)perimanGetPinBus(pin, ESP32_BUS_TYPE_LEDC);
|
||||
if (bus != NULL) {
|
||||
gpio_set_level(pin, out_invert);
|
||||
#ifdef SOC_LEDC_SUPPORT_HS_MODE
|
||||
esp_rom_gpio_connect_out_signal(pin, ((bus->channel / 8 == 0) ? LEDC_HS_SIG_OUT0_IDX : LEDC_LS_SIG_OUT0_IDX) + ((bus->channel) % 8), out_invert, 0);
|
||||
#else
|
||||
esp_rom_gpio_connect_out_signal(pin, LEDC_LS_SIG_OUT0_IDX + ((bus->channel) % 8), out_invert, 0);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static IRAM_ATTR bool ledcFnWrapper(const ledc_cb_param_t *param, void *user_arg) {
|
||||
if (param->event == LEDC_FADE_END_EVT) {
|
||||
ledc_channel_handle_t *bus = (ledc_channel_handle_t *)user_arg;
|
||||
#ifndef SOC_LEDC_SUPPORT_FADE_STOP
|
||||
portBASE_TYPE xTaskWoken = 0;
|
||||
xSemaphoreGiveFromISR(bus->lock, &xTaskWoken);
|
||||
#endif
|
||||
if (bus->fn) {
|
||||
if (bus->arg) {
|
||||
((voidFuncPtrArg)bus->fn)(bus->arg);
|
||||
} else {
|
||||
bus->fn();
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ledcFadeConfig(uint8_t pin, uint32_t start_duty, uint32_t target_duty, int max_fade_time_ms, void (*userFunc)(void *), void *arg) {
|
||||
ledc_channel_handle_t *bus = (ledc_channel_handle_t *)perimanGetPinBus(pin, ESP32_BUS_TYPE_LEDC);
|
||||
if (bus != NULL) {
|
||||
|
||||
#ifndef SOC_LEDC_SUPPORT_FADE_STOP
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
if (bus->lock == NULL) {
|
||||
bus->lock = xSemaphoreCreateBinary();
|
||||
if (bus->lock == NULL) {
|
||||
log_e("xSemaphoreCreateBinary failed");
|
||||
return false;
|
||||
}
|
||||
xSemaphoreGive(bus->lock);
|
||||
}
|
||||
//acquire lock
|
||||
if (xSemaphoreTake(bus->lock, 0) != pdTRUE) {
|
||||
log_e("LEDC Fade is still running on pin %u! SoC does not support stopping fade.", pin);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
uint8_t group = (bus->channel / 8), channel = (bus->channel % 8);
|
||||
|
||||
// Initialize fade service.
|
||||
if (!fade_initialized) {
|
||||
ledc_fade_func_install(0);
|
||||
fade_initialized = true;
|
||||
}
|
||||
|
||||
bus->fn = (voidFuncPtr)userFunc;
|
||||
bus->arg = arg;
|
||||
|
||||
ledc_cbs_t callbacks = {.fade_cb = ledcFnWrapper};
|
||||
ledc_cb_register(group, channel, &callbacks, (void *)bus);
|
||||
|
||||
//Fixing if all bits in resolution is set = LEDC FULL ON
|
||||
uint32_t max_duty = (1 << bus->channel_resolution) - 1;
|
||||
|
||||
if ((target_duty == max_duty) && (max_duty != 1)) {
|
||||
target_duty = max_duty + 1;
|
||||
} else if ((start_duty == max_duty) && (max_duty != 1)) {
|
||||
start_duty = max_duty + 1;
|
||||
}
|
||||
|
||||
#if SOC_LEDC_SUPPORT_FADE_STOP
|
||||
ledc_fade_stop(group, channel);
|
||||
#endif
|
||||
|
||||
if (ledc_set_duty_and_update(group, channel, start_duty, 0) != ESP_OK) {
|
||||
log_e("ledc_set_duty_and_update failed");
|
||||
return false;
|
||||
}
|
||||
// Wait for LEDCs next PWM cycle to update duty (~ 1-2 ms)
|
||||
while (ledc_get_duty(group, channel) != start_duty);
|
||||
|
||||
if (ledc_set_fade_time_and_start(group, channel, target_duty, max_fade_time_ms, LEDC_FADE_NO_WAIT) != ESP_OK) {
|
||||
log_e("ledc_set_fade_time_and_start failed");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
log_e("Pin %u is not attached to LEDC. Call ledcAttach first!", pin);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ledcFade(uint8_t pin, uint32_t start_duty, uint32_t target_duty, int max_fade_time_ms) {
|
||||
return ledcFadeConfig(pin, start_duty, target_duty, max_fade_time_ms, NULL, NULL);
|
||||
}
|
||||
|
||||
bool ledcFadeWithInterrupt(uint8_t pin, uint32_t start_duty, uint32_t target_duty, int max_fade_time_ms, voidFuncPtr userFunc) {
|
||||
return ledcFadeConfig(pin, start_duty, target_duty, max_fade_time_ms, (voidFuncPtrArg)userFunc, NULL);
|
||||
}
|
||||
|
||||
bool ledcFadeWithInterruptArg(uint8_t pin, uint32_t start_duty, uint32_t target_duty, int max_fade_time_ms, void (*userFunc)(void *), void *arg) {
|
||||
return ledcFadeConfig(pin, start_duty, target_duty, max_fade_time_ms, userFunc, arg);
|
||||
}
|
||||
|
||||
static uint8_t analog_resolution = 8;
|
||||
static int analog_frequency = 1000;
|
||||
void analogWrite(uint8_t pin, int value) {
|
||||
// Use ledc hardware for internal pins
|
||||
if (pin < SOC_GPIO_PIN_COUNT) {
|
||||
ledc_channel_handle_t *bus = (ledc_channel_handle_t *)perimanGetPinBus(pin, ESP32_BUS_TYPE_LEDC);
|
||||
if (bus == NULL && perimanClearPinBus(pin)) {
|
||||
if (ledcAttach(pin, analog_frequency, analog_resolution) == 0) {
|
||||
log_e("analogWrite setup failed (freq = %u, resolution = %u). Try setting different resolution or frequency");
|
||||
return;
|
||||
}
|
||||
}
|
||||
ledcWrite(pin, value);
|
||||
}
|
||||
}
|
||||
|
||||
void analogWriteFrequency(uint8_t pin, uint32_t freq) {
|
||||
if (ledcChangeFrequency(pin, freq, analog_resolution) == 0) {
|
||||
log_e("analogWrite frequency cant be set due to selected resolution! Try to adjust resolution first");
|
||||
return;
|
||||
}
|
||||
analog_frequency = freq;
|
||||
}
|
||||
|
||||
void analogWriteResolution(uint8_t pin, uint8_t resolution) {
|
||||
if (ledcChangeFrequency(pin, analog_frequency, resolution) == 0) {
|
||||
log_e("analogWrite resolution cant be set due to selected frequency! Try to adjust frequency first");
|
||||
return;
|
||||
}
|
||||
analog_resolution = resolution;
|
||||
}
|
||||
|
||||
#endif /* SOC_LEDC_SUPPORTED */
|
||||
|
|
@ -1,221 +0,0 @@
|
|||
// Copyright 2015-2023 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// 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.
|
||||
|
||||
#ifndef _ESP32_HAL_LEDC_H_
|
||||
#define _ESP32_HAL_LEDC_H_
|
||||
|
||||
#include "soc/soc_caps.h"
|
||||
#if SOC_LEDC_SUPPORTED
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
|
||||
typedef enum {
|
||||
NOTE_C,
|
||||
NOTE_Cs,
|
||||
NOTE_D,
|
||||
NOTE_Eb,
|
||||
NOTE_E,
|
||||
NOTE_F,
|
||||
NOTE_Fs,
|
||||
NOTE_G,
|
||||
NOTE_Gs,
|
||||
NOTE_A,
|
||||
NOTE_Bb,
|
||||
NOTE_B,
|
||||
NOTE_MAX
|
||||
} note_t;
|
||||
|
||||
typedef void (*voidFuncPtr)(void);
|
||||
typedef void (*voidFuncPtrArg)(void *);
|
||||
|
||||
typedef struct {
|
||||
uint8_t pin; // Pin assigned to channel
|
||||
uint8_t channel; // Channel number
|
||||
uint8_t channel_resolution; // Resolution of channel
|
||||
voidFuncPtr fn;
|
||||
void *arg;
|
||||
#ifndef SOC_LEDC_SUPPORT_FADE_STOP
|
||||
SemaphoreHandle_t lock; //xSemaphoreCreateBinary
|
||||
#endif
|
||||
} ledc_channel_handle_t;
|
||||
|
||||
/**
|
||||
* @brief Attach a pin to the LEDC driver, with a given frequency and resolution.
|
||||
* Channel is automatically assigned.
|
||||
*
|
||||
* @param pin GPIO pin
|
||||
* @param freq frequency of PWM signal
|
||||
* @param resolution resolution for LEDC pin
|
||||
*
|
||||
* @return true if configuration is successful and pin was successfully attached, false otherwise.
|
||||
*/
|
||||
bool ledcAttach(uint8_t pin, uint32_t freq, uint8_t resolution);
|
||||
|
||||
/**
|
||||
* @brief Attach a pin to the LEDC driver, with a given frequency, resolution and channel.
|
||||
*
|
||||
* @param pin GPIO pin
|
||||
* @param freq frequency of PWM signal
|
||||
* @param resolution resolution for LEDC pin
|
||||
* @param channel LEDC channel to attach to
|
||||
*
|
||||
* @return true if configuration is successful and pin was successfully attached, false otherwise.
|
||||
*/
|
||||
bool ledcAttachChannel(uint8_t pin, uint32_t freq, uint8_t resolution, uint8_t channel);
|
||||
|
||||
/**
|
||||
* @brief Set the duty cycle of a given pin.
|
||||
*
|
||||
* @param pin GPIO pin
|
||||
* @param duty duty cycle to set
|
||||
*
|
||||
* @return true if duty cycle was successfully set, false otherwise.
|
||||
*/
|
||||
bool ledcWrite(uint8_t pin, uint32_t duty);
|
||||
|
||||
/**
|
||||
* @brief Set the duty cycle of a given channel.
|
||||
*
|
||||
* @param channel LEDC channel
|
||||
* @param duty duty cycle to set
|
||||
*
|
||||
* @return true if duty cycle was successfully set, false otherwise.
|
||||
*/
|
||||
bool ledcWriteChannel(uint8_t channel, uint32_t duty);
|
||||
|
||||
/**
|
||||
* @brief Sets the duty to 50 % PWM tone on selected frequency.
|
||||
*
|
||||
* @param pin GPIO pin
|
||||
* @param freq select frequency of pwm signal. If frequency is 0, duty will be set to 0.
|
||||
*
|
||||
* @return frequency if tone was successfully set.
|
||||
* If ``0`` is returned, error occurs and LEDC pin was not configured.
|
||||
*/
|
||||
uint32_t ledcWriteTone(uint8_t pin, uint32_t freq);
|
||||
|
||||
/**
|
||||
* @brief Sets the LEDC pin to specific note.
|
||||
*
|
||||
* @param pin GPIO pin
|
||||
* @param note select note to be set (NOTE_C, NOTE_Cs, NOTE_D, NOTE_Eb, NOTE_E, NOTE_F, NOTE_Fs, NOTE_G, NOTE_Gs, NOTE_A, NOTE_Bb, NOTE_B).
|
||||
* @param octave select octave for note.
|
||||
*
|
||||
* @return frequency if note was successfully set.
|
||||
* If ``0`` is returned, error occurs and LEDC pin was not configured.
|
||||
*/
|
||||
uint32_t ledcWriteNote(uint8_t pin, note_t note, uint8_t octave);
|
||||
|
||||
/**
|
||||
* @brief Read the duty cycle of a given LEDC pin.
|
||||
*
|
||||
* @param pin GPIO pin
|
||||
*
|
||||
* @return duty cycle of selected LEDC pin.
|
||||
*/
|
||||
uint32_t ledcRead(uint8_t pin);
|
||||
|
||||
/**
|
||||
* @brief Read the frequency of a given LEDC pin.
|
||||
*
|
||||
* @param pin GPIO pin
|
||||
*
|
||||
* @return frequency of selected LEDC pin.
|
||||
*/
|
||||
uint32_t ledcReadFreq(uint8_t pin);
|
||||
|
||||
/**
|
||||
* @brief Detach a pin from the LEDC driver.
|
||||
*
|
||||
* @param pin GPIO pin
|
||||
*
|
||||
* @return true if pin was successfully detached, false otherwise.
|
||||
*/
|
||||
bool ledcDetach(uint8_t pin);
|
||||
|
||||
/**
|
||||
* @brief Change the frequency and resolution of a given LEDC pin.
|
||||
*
|
||||
* @param pin GPIO pin
|
||||
* @param freq frequency of PWM signal
|
||||
* @param resolution resolution for LEDC pin
|
||||
*
|
||||
* @return frequency configured for the LEDC channel.
|
||||
* If ``0`` is returned, error occurs and LEDC pin was not configured.
|
||||
*/
|
||||
uint32_t ledcChangeFrequency(uint8_t pin, uint32_t freq, uint8_t resolution);
|
||||
|
||||
/**
|
||||
* @brief Sets inverting of the output signal for a given LEDC pin.
|
||||
*
|
||||
* @param pin GPIO pin
|
||||
* @param out_invert select, if output should be inverted (true = inverting output).
|
||||
*
|
||||
* @return true if output inverting was successfully set, false otherwise.
|
||||
*/
|
||||
bool ledcOutputInvert(uint8_t pin, bool out_invert);
|
||||
|
||||
//Fade functions
|
||||
/**
|
||||
* @brief Setup and start a fade on a given LEDC pin.
|
||||
*
|
||||
* @param pin GPIO pin
|
||||
* @param start_duty initial duty cycle of the fade
|
||||
* @param target_duty target duty cycle of the fade
|
||||
* @param max_fade_time_ms maximum fade time in milliseconds
|
||||
*
|
||||
* @return true if fade was successfully set and started, false otherwise.
|
||||
*/
|
||||
bool ledcFade(uint8_t pin, uint32_t start_duty, uint32_t target_duty, int max_fade_time_ms);
|
||||
|
||||
/**
|
||||
* @brief Setup and start a fade on a given LEDC pin with a callback function.
|
||||
*
|
||||
* @param pin GPIO pin
|
||||
* @param start_duty initial duty cycle of the fade
|
||||
* @param target_duty target duty cycle of the fade
|
||||
* @param max_fade_time_ms maximum fade time in milliseconds
|
||||
* @param userFunc callback function to be called after fade is finished
|
||||
*
|
||||
* @return true if fade was successfully set and started, false otherwise.
|
||||
*/
|
||||
bool ledcFadeWithInterrupt(uint8_t pin, uint32_t start_duty, uint32_t target_duty, int max_fade_time_ms, void (*userFunc)(void));
|
||||
|
||||
/**
|
||||
* @brief Setup and start a fade on a given LEDC pin with a callback function and argument.
|
||||
*
|
||||
* @param pin GPIO pin
|
||||
* @param start_duty initial duty cycle of the fade
|
||||
* @param target_duty target duty cycle of the fade
|
||||
* @param max_fade_time_ms maximum fade time in milliseconds
|
||||
* @param userFunc callback function to be called after fade is finished
|
||||
* @param arg argument to be passed to the callback function
|
||||
*
|
||||
* @return true if fade was successfully set and started, false otherwise.
|
||||
*/
|
||||
bool ledcFadeWithInterruptArg(uint8_t pin, uint32_t start_duty, uint32_t target_duty, int max_fade_time_ms, void (*userFunc)(void *), void *arg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SOC_LEDC_SUPPORTED */
|
||||
#endif /* _ESP32_HAL_LEDC_H_ */
|
||||
|
|
@ -1,348 +0,0 @@
|
|||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// 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.
|
||||
#ifndef __ARDUHAL_LOG_H__
|
||||
#define __ARDUHAL_LOG_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_timer.h"
|
||||
|
||||
#define ARDUHAL_LOG_LEVEL_NONE (0)
|
||||
#define ARDUHAL_LOG_LEVEL_ERROR (1)
|
||||
#define ARDUHAL_LOG_LEVEL_WARN (2)
|
||||
#define ARDUHAL_LOG_LEVEL_INFO (3)
|
||||
#define ARDUHAL_LOG_LEVEL_DEBUG (4)
|
||||
#define ARDUHAL_LOG_LEVEL_VERBOSE (5)
|
||||
|
||||
#ifndef CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL
|
||||
#define CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL ARDUHAL_LOG_LEVEL_NONE
|
||||
#endif
|
||||
|
||||
#ifndef CORE_DEBUG_LEVEL
|
||||
#define ARDUHAL_LOG_LEVEL CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL
|
||||
#else
|
||||
#define ARDUHAL_LOG_LEVEL CORE_DEBUG_LEVEL
|
||||
#ifdef USE_ESP_IDF_LOG
|
||||
#ifndef LOG_LOCAL_LEVEL
|
||||
#define LOG_LOCAL_LEVEL CORE_DEBUG_LEVEL
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_ARDUHAL_LOG_COLORS
|
||||
#define CONFIG_ARDUHAL_LOG_COLORS 0
|
||||
#endif
|
||||
|
||||
#if CONFIG_ARDUHAL_LOG_COLORS
|
||||
#define ARDUHAL_LOG_COLOR_BLACK "30"
|
||||
#define ARDUHAL_LOG_COLOR_RED "31" //ERROR
|
||||
#define ARDUHAL_LOG_COLOR_GREEN "32" //INFO
|
||||
#define ARDUHAL_LOG_COLOR_YELLOW "33" //WARNING
|
||||
#define ARDUHAL_LOG_COLOR_BLUE "34"
|
||||
#define ARDUHAL_LOG_COLOR_MAGENTA "35"
|
||||
#define ARDUHAL_LOG_COLOR_CYAN "36" //DEBUG
|
||||
#define ARDUHAL_LOG_COLOR_GRAY "37" //VERBOSE
|
||||
#define ARDUHAL_LOG_COLOR_WHITE "38"
|
||||
|
||||
#define ARDUHAL_LOG_COLOR(COLOR) "\033[0;" COLOR "m"
|
||||
#define ARDUHAL_LOG_BOLD(COLOR) "\033[1;" COLOR "m"
|
||||
#define ARDUHAL_LOG_RESET_COLOR "\033[0m"
|
||||
|
||||
#define ARDUHAL_LOG_COLOR_E ARDUHAL_LOG_COLOR(ARDUHAL_LOG_COLOR_RED)
|
||||
#define ARDUHAL_LOG_COLOR_W ARDUHAL_LOG_COLOR(ARDUHAL_LOG_COLOR_YELLOW)
|
||||
#define ARDUHAL_LOG_COLOR_I ARDUHAL_LOG_COLOR(ARDUHAL_LOG_COLOR_GREEN)
|
||||
#define ARDUHAL_LOG_COLOR_D ARDUHAL_LOG_COLOR(ARDUHAL_LOG_COLOR_CYAN)
|
||||
#define ARDUHAL_LOG_COLOR_V ARDUHAL_LOG_COLOR(ARDUHAL_LOG_COLOR_GRAY)
|
||||
#define ARDUHAL_LOG_COLOR_PRINT(letter) log_printf(ARDUHAL_LOG_COLOR_##letter)
|
||||
#define ARDUHAL_LOG_COLOR_PRINT_END log_printf(ARDUHAL_LOG_RESET_COLOR)
|
||||
#else
|
||||
#define ARDUHAL_LOG_COLOR_E
|
||||
#define ARDUHAL_LOG_COLOR_W
|
||||
#define ARDUHAL_LOG_COLOR_I
|
||||
#define ARDUHAL_LOG_COLOR_D
|
||||
#define ARDUHAL_LOG_COLOR_V
|
||||
#define ARDUHAL_LOG_RESET_COLOR
|
||||
#define ARDUHAL_LOG_COLOR_PRINT(letter)
|
||||
#define ARDUHAL_LOG_COLOR_PRINT_END
|
||||
#endif
|
||||
|
||||
#ifdef USE_ESP_IDF_LOG
|
||||
#ifndef ARDUHAL_ESP_LOG_TAG
|
||||
#define ARDUHAL_ESP_LOG_TAG "ARDUINO"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
const char *pathToFileName(const char *path);
|
||||
int log_printf(const char *fmt, ...);
|
||||
void log_print_buf(const uint8_t *b, size_t len);
|
||||
|
||||
#define ARDUHAL_SHORT_LOG_FORMAT(letter, format) ARDUHAL_LOG_COLOR_##letter format ARDUHAL_LOG_RESET_COLOR "\r\n"
|
||||
#define ARDUHAL_LOG_FORMAT(letter, format) \
|
||||
ARDUHAL_LOG_COLOR_##letter "[%6u][" #letter "][%s:%u] %s(): " format ARDUHAL_LOG_RESET_COLOR "\r\n", (unsigned long)(esp_timer_get_time() / 1000ULL), \
|
||||
pathToFileName(__FILE__), __LINE__, __FUNCTION__
|
||||
|
||||
//esp_rom_printf(DRAM_STR("ST:%d\n"), frame_pos);
|
||||
|
||||
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_VERBOSE
|
||||
#ifndef USE_ESP_IDF_LOG
|
||||
#define log_v(format, ...) log_printf(ARDUHAL_LOG_FORMAT(V, format), ##__VA_ARGS__)
|
||||
#define isr_log_v(format, ...) ets_printf(ARDUHAL_LOG_FORMAT(V, format), ##__VA_ARGS__)
|
||||
#define log_buf_v(b, l) \
|
||||
do { \
|
||||
ARDUHAL_LOG_COLOR_PRINT(V); \
|
||||
log_print_buf(b, l); \
|
||||
ARDUHAL_LOG_COLOR_PRINT_END; \
|
||||
} while (0)
|
||||
#else
|
||||
#define log_v(format, ...) \
|
||||
do { \
|
||||
ESP_LOG_LEVEL_LOCAL(ESP_LOG_VERBOSE, ARDUHAL_ESP_LOG_TAG, format, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#define isr_log_v(format, ...) \
|
||||
do { \
|
||||
ets_printf(LOG_FORMAT(V, format), esp_log_timestamp(), ARDUHAL_ESP_LOG_TAG, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#define log_buf_v(b, l) \
|
||||
do { \
|
||||
ESP_LOG_BUFFER_HEXDUMP(ARDUHAL_ESP_LOG_TAG, b, l, ESP_LOG_VERBOSE); \
|
||||
} while (0)
|
||||
#endif
|
||||
#else
|
||||
#define log_v(format, ...) \
|
||||
do { \
|
||||
} while (0)
|
||||
#define isr_log_v(format, ...) \
|
||||
do { \
|
||||
} while (0)
|
||||
#define log_buf_v(b, l) \
|
||||
do { \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_DEBUG
|
||||
#ifndef USE_ESP_IDF_LOG
|
||||
#define log_d(format, ...) log_printf(ARDUHAL_LOG_FORMAT(D, format), ##__VA_ARGS__)
|
||||
#define isr_log_d(format, ...) ets_printf(ARDUHAL_LOG_FORMAT(D, format), ##__VA_ARGS__)
|
||||
#define log_buf_d(b, l) \
|
||||
do { \
|
||||
ARDUHAL_LOG_COLOR_PRINT(D); \
|
||||
log_print_buf(b, l); \
|
||||
ARDUHAL_LOG_COLOR_PRINT_END; \
|
||||
} while (0)
|
||||
#else
|
||||
#define log_d(format, ...) \
|
||||
do { \
|
||||
ESP_LOG_LEVEL_LOCAL(ESP_LOG_DEBUG, ARDUHAL_ESP_LOG_TAG, format, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#define isr_log_d(format, ...) \
|
||||
do { \
|
||||
ets_printf(LOG_FORMAT(D, format), esp_log_timestamp(), ARDUHAL_ESP_LOG_TAG, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#define log_buf_d(b, l) \
|
||||
do { \
|
||||
ESP_LOG_BUFFER_HEXDUMP(ARDUHAL_ESP_LOG_TAG, b, l, ESP_LOG_DEBUG); \
|
||||
} while (0)
|
||||
#endif
|
||||
#else
|
||||
#define log_d(format, ...) \
|
||||
do { \
|
||||
} while (0)
|
||||
#define isr_log_d(format, ...) \
|
||||
do { \
|
||||
} while (0)
|
||||
#define log_buf_d(b, l) \
|
||||
do { \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO
|
||||
#ifndef USE_ESP_IDF_LOG
|
||||
#define log_i(format, ...) log_printf(ARDUHAL_LOG_FORMAT(I, format), ##__VA_ARGS__)
|
||||
#define isr_log_i(format, ...) ets_printf(ARDUHAL_LOG_FORMAT(I, format), ##__VA_ARGS__)
|
||||
#define log_buf_i(b, l) \
|
||||
do { \
|
||||
ARDUHAL_LOG_COLOR_PRINT(I); \
|
||||
log_print_buf(b, l); \
|
||||
ARDUHAL_LOG_COLOR_PRINT_END; \
|
||||
} while (0)
|
||||
#else
|
||||
#define log_i(format, ...) \
|
||||
do { \
|
||||
ESP_LOG_LEVEL_LOCAL(ESP_LOG_INFO, ARDUHAL_ESP_LOG_TAG, format, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#define isr_log_i(format, ...) \
|
||||
do { \
|
||||
ets_printf(LOG_FORMAT(I, format), esp_log_timestamp(), ARDUHAL_ESP_LOG_TAG, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#define log_buf_i(b, l) \
|
||||
do { \
|
||||
ESP_LOG_BUFFER_HEXDUMP(ARDUHAL_ESP_LOG_TAG, b, l, ESP_LOG_INFO); \
|
||||
} while (0)
|
||||
#endif
|
||||
#else
|
||||
#define log_i(format, ...) \
|
||||
do { \
|
||||
} while (0)
|
||||
#define isr_log_i(format, ...) \
|
||||
do { \
|
||||
} while (0)
|
||||
#define log_buf_i(b, l) \
|
||||
do { \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_WARN
|
||||
#ifndef USE_ESP_IDF_LOG
|
||||
#define log_w(format, ...) log_printf(ARDUHAL_LOG_FORMAT(W, format), ##__VA_ARGS__)
|
||||
#define isr_log_w(format, ...) ets_printf(ARDUHAL_LOG_FORMAT(W, format), ##__VA_ARGS__)
|
||||
#define log_buf_w(b, l) \
|
||||
do { \
|
||||
ARDUHAL_LOG_COLOR_PRINT(W); \
|
||||
log_print_buf(b, l); \
|
||||
ARDUHAL_LOG_COLOR_PRINT_END; \
|
||||
} while (0)
|
||||
#else
|
||||
#define log_w(format, ...) \
|
||||
do { \
|
||||
ESP_LOG_LEVEL_LOCAL(ESP_LOG_WARN, ARDUHAL_ESP_LOG_TAG, format, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#define isr_log_w(format, ...) \
|
||||
do { \
|
||||
ets_printf(LOG_FORMAT(W, format), esp_log_timestamp(), ARDUHAL_ESP_LOG_TAG, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#define log_buf_w(b, l) \
|
||||
do { \
|
||||
ESP_LOG_BUFFER_HEXDUMP(ARDUHAL_ESP_LOG_TAG, b, l, ESP_LOG_WARN); \
|
||||
} while (0)
|
||||
#endif
|
||||
#else
|
||||
#define log_w(format, ...) \
|
||||
do { \
|
||||
} while (0)
|
||||
#define isr_log_w(format, ...) \
|
||||
do { \
|
||||
} while (0)
|
||||
#define log_buf_w(b, l) \
|
||||
do { \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_ERROR
|
||||
#ifndef USE_ESP_IDF_LOG
|
||||
#define log_e(format, ...) log_printf(ARDUHAL_LOG_FORMAT(E, format), ##__VA_ARGS__)
|
||||
#define isr_log_e(format, ...) ets_printf(ARDUHAL_LOG_FORMAT(E, format), ##__VA_ARGS__)
|
||||
#define log_buf_e(b, l) \
|
||||
do { \
|
||||
ARDUHAL_LOG_COLOR_PRINT(E); \
|
||||
log_print_buf(b, l); \
|
||||
ARDUHAL_LOG_COLOR_PRINT_END; \
|
||||
} while (0)
|
||||
#else
|
||||
#define log_e(format, ...) \
|
||||
do { \
|
||||
ESP_LOG_LEVEL_LOCAL(ESP_LOG_ERROR, ARDUHAL_ESP_LOG_TAG, format, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#define isr_log_e(format, ...) \
|
||||
do { \
|
||||
ets_printf(LOG_FORMAT(E, format), esp_log_timestamp(), ARDUHAL_ESP_LOG_TAG, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#define log_buf_e(b, l) \
|
||||
do { \
|
||||
ESP_LOG_BUFFER_HEXDUMP(ARDUHAL_ESP_LOG_TAG, b, l, ESP_LOG_ERROR); \
|
||||
} while (0)
|
||||
#endif
|
||||
#else
|
||||
#define log_e(format, ...) \
|
||||
do { \
|
||||
} while (0)
|
||||
#define isr_log_e(format, ...) \
|
||||
do { \
|
||||
} while (0)
|
||||
#define log_buf_e(b, l) \
|
||||
do { \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_NONE
|
||||
#ifndef USE_ESP_IDF_LOG
|
||||
#define log_n(format, ...) log_printf(ARDUHAL_LOG_FORMAT(E, format), ##__VA_ARGS__)
|
||||
#define isr_log_n(format, ...) ets_printf(ARDUHAL_LOG_FORMAT(E, format), ##__VA_ARGS__)
|
||||
#define log_buf_n(b, l) \
|
||||
do { \
|
||||
ARDUHAL_LOG_COLOR_PRINT(E); \
|
||||
log_print_buf(b, l); \
|
||||
ARDUHAL_LOG_COLOR_PRINT_END; \
|
||||
} while (0)
|
||||
#else
|
||||
#define log_n(format, ...) \
|
||||
do { \
|
||||
ESP_LOG_LEVEL_LOCAL(ESP_LOG_ERROR, ARDUHAL_ESP_LOG_TAG, format, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#define isr_log_n(format, ...) \
|
||||
do { \
|
||||
ets_printf(LOG_FORMAT(E, format), esp_log_timestamp(), ARDUHAL_ESP_LOG_TAG, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#define log_buf_n(b, l) \
|
||||
do { \
|
||||
ESP_LOG_BUFFER_HEXDUMP(ARDUHAL_ESP_LOG_TAG, b, l, ESP_LOG_ERROR); \
|
||||
} while (0)
|
||||
#endif
|
||||
#else
|
||||
#define log_n(format, ...) \
|
||||
do { \
|
||||
} while (0)
|
||||
#define isr_log_n(format, ...) \
|
||||
do { \
|
||||
} while (0)
|
||||
#define log_buf_n(b, l) \
|
||||
do { \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#include "esp_log.h"
|
||||
|
||||
#ifndef USE_ESP_IDF_LOG
|
||||
#ifdef CONFIG_ARDUHAL_ESP_LOG
|
||||
#undef ESP_LOGE
|
||||
#undef ESP_LOGW
|
||||
#undef ESP_LOGI
|
||||
#undef ESP_LOGD
|
||||
#undef ESP_LOGV
|
||||
#undef ESP_EARLY_LOGE
|
||||
#undef ESP_EARLY_LOGW
|
||||
#undef ESP_EARLY_LOGI
|
||||
#undef ESP_EARLY_LOGD
|
||||
#undef ESP_EARLY_LOGV
|
||||
|
||||
#define ESP_LOGE(tag, format, ...) log_e("[%s] " format, tag, ##__VA_ARGS__)
|
||||
#define ESP_LOGW(tag, format, ...) log_w("[%s] " format, tag, ##__VA_ARGS__)
|
||||
#define ESP_LOGI(tag, format, ...) log_i("[%s] " format, tag, ##__VA_ARGS__)
|
||||
#define ESP_LOGD(tag, format, ...) log_d("[%s] " format, tag, ##__VA_ARGS__)
|
||||
#define ESP_LOGV(tag, format, ...) log_v("[%s] " format, tag, ##__VA_ARGS__)
|
||||
#define ESP_EARLY_LOGE(tag, format, ...) isr_log_e("[%s] " format, tag, ##__VA_ARGS__)
|
||||
#define ESP_EARLY_LOGW(tag, format, ...) isr_log_w("[%s] " format, tag, ##__VA_ARGS__)
|
||||
#define ESP_EARLY_LOGI(tag, format, ...) isr_log_i("[%s] " format, tag, ##__VA_ARGS__)
|
||||
#define ESP_EARLY_LOGD(tag, format, ...) isr_log_d("[%s] " format, tag, ##__VA_ARGS__)
|
||||
#define ESP_EARLY_LOGV(tag, format, ...) isr_log_v("[%s] " format, tag, ##__VA_ARGS__)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __ESP_LOGGING_H__ */
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// 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.
|
||||
|
||||
#include "esp32-hal-matrix.h"
|
||||
#include "esp_attr.h"
|
||||
|
||||
#include "esp_system.h"
|
||||
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
|
||||
#include "soc/gpio_pins.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
|
||||
#include "esp32/rom/gpio.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#include "esp32s2/rom/gpio.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
#include "esp32s3/rom/gpio.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32C2
|
||||
#include "esp32c2/rom/gpio.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||
#include "esp32c3/rom/gpio.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32C6
|
||||
#include "esp32c6/rom/gpio.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||
#include "esp32h2/rom/gpio.h"
|
||||
#else
|
||||
#error Target CONFIG_IDF_TARGET is not supported
|
||||
#endif
|
||||
#else // ESP32 Before IDF 4.0
|
||||
#include "rom/gpio.h"
|
||||
#define GPIO_MATRIX_CONST_ZERO_INPUT GPIO_FUNC_IN_LOW
|
||||
#define GPIO_MATRIX_CONST_ONE_INPUT GPIO_FUNC_IN_HIGH
|
||||
#endif
|
||||
|
||||
void ARDUINO_ISR_ATTR pinMatrixOutAttach(uint8_t pin, uint8_t function, bool invertOut, bool invertEnable) {
|
||||
gpio_matrix_out(pin, function, invertOut, invertEnable);
|
||||
}
|
||||
|
||||
void ARDUINO_ISR_ATTR pinMatrixOutDetach(uint8_t pin, bool invertOut, bool invertEnable) {
|
||||
gpio_matrix_out(pin, SIG_GPIO_OUT_IDX, invertOut, invertEnable);
|
||||
}
|
||||
|
||||
void ARDUINO_ISR_ATTR pinMatrixInAttach(uint8_t pin, uint8_t signal, bool inverted) {
|
||||
gpio_matrix_in(pin, signal, inverted);
|
||||
}
|
||||
|
||||
void ARDUINO_ISR_ATTR pinMatrixInDetach(uint8_t signal, bool high, bool inverted) {
|
||||
gpio_matrix_in(high ? GPIO_MATRIX_CONST_ONE_INPUT : GPIO_MATRIX_CONST_ZERO_INPUT, signal, inverted);
|
||||
}
|
||||
/*
|
||||
void ARDUINO_ISR_ATTR intrMatrixAttach(uint32_t source, uint32_t inum){
|
||||
intr_matrix_set(PRO_CPU_NUM, source, inum);
|
||||
}
|
||||
*/
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// 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.
|
||||
|
||||
#ifndef _ESP32_HAL_MATRIX_H_
|
||||
#define _ESP32_HAL_MATRIX_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "esp32-hal.h"
|
||||
#include "soc/gpio_sig_map.h"
|
||||
|
||||
void pinMatrixOutAttach(uint8_t pin, uint8_t function, bool invertOut, bool invertEnable);
|
||||
void pinMatrixOutDetach(uint8_t pin, bool invertOut, bool invertEnable);
|
||||
void pinMatrixInAttach(uint8_t pin, uint8_t signal, bool inverted);
|
||||
void pinMatrixInDetach(uint8_t signal, bool high, bool inverted);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* COMPONENTS_ARDUHAL_INCLUDE_ESP32_HAL_MATRIX_H_ */
|
||||
|
|
@ -1,404 +0,0 @@
|
|||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// 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.
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_attr.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "nvs.h"
|
||||
#include "esp_partition.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_timer.h"
|
||||
#ifdef CONFIG_APP_ROLLBACK_ENABLE
|
||||
#include "esp_ota_ops.h"
|
||||
#endif //CONFIG_APP_ROLLBACK_ENABLE
|
||||
#ifdef CONFIG_BT_ENABLED
|
||||
#include "esp_bt.h"
|
||||
#endif //CONFIG_BT_ENABLED
|
||||
#include <sys/time.h>
|
||||
#include "soc/rtc.h"
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32C2) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32H2)
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
#include "soc/apb_ctrl_reg.h"
|
||||
#endif
|
||||
#include "esp_task_wdt.h"
|
||||
#include "esp32-hal.h"
|
||||
|
||||
#include "esp_system.h"
|
||||
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
|
||||
#include "esp32/rom/rtc.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#include "esp32s2/rom/rtc.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
#include "esp32s3/rom/rtc.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32C2
|
||||
#include "esp32c2/rom/rtc.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||
#include "esp32c3/rom/rtc.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32C6
|
||||
#include "esp32c6/rom/rtc.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||
#include "esp32h2/rom/rtc.h"
|
||||
|
||||
#else
|
||||
#error Target CONFIG_IDF_TARGET is not supported
|
||||
#endif
|
||||
|
||||
#if SOC_TEMP_SENSOR_SUPPORTED
|
||||
#include "driver/temperature_sensor.h"
|
||||
#endif
|
||||
|
||||
#else // ESP32 Before IDF 4.0
|
||||
#include "rom/rtc.h"
|
||||
#endif
|
||||
|
||||
//Undocumented!!! Get chip temperature in Fahrenheit
|
||||
//Source: https://github.com/pcbreflux/espressif/blob/master/esp32/arduino/sketchbook/ESP32_int_temp_sensor/ESP32_int_temp_sensor.ino
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
uint8_t temprature_sens_read();
|
||||
|
||||
float temperatureRead() {
|
||||
return (temprature_sens_read() - 32) / 1.8;
|
||||
}
|
||||
#elif SOC_TEMP_SENSOR_SUPPORTED
|
||||
static temperature_sensor_handle_t temp_sensor = NULL;
|
||||
|
||||
static bool temperatureReadInit() {
|
||||
static volatile bool initialized = false;
|
||||
if (!initialized) {
|
||||
initialized = true;
|
||||
//Install temperature sensor, expected temp ranger range: 10~50 ℃
|
||||
temperature_sensor_config_t temp_sensor_config = TEMPERATURE_SENSOR_CONFIG_DEFAULT(10, 50);
|
||||
if (temperature_sensor_install(&temp_sensor_config, &temp_sensor) != ESP_OK) {
|
||||
initialized = false;
|
||||
temp_sensor = NULL;
|
||||
log_e("temperature_sensor_install failed");
|
||||
} else if (temperature_sensor_enable(temp_sensor) != ESP_OK) {
|
||||
temperature_sensor_uninstall(temp_sensor);
|
||||
initialized = false;
|
||||
temp_sensor = NULL;
|
||||
log_e("temperature_sensor_enable failed");
|
||||
}
|
||||
}
|
||||
return initialized;
|
||||
}
|
||||
|
||||
float temperatureRead() {
|
||||
float result = NAN;
|
||||
if (temperatureReadInit()) {
|
||||
if (temperature_sensor_get_celsius(temp_sensor, &result) != ESP_OK) {
|
||||
log_e("temperature_sensor_get_celsius failed");
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
void __yield() {
|
||||
vPortYield();
|
||||
}
|
||||
|
||||
void yield() __attribute__((weak, alias("__yield")));
|
||||
|
||||
#if CONFIG_AUTOSTART_ARDUINO
|
||||
|
||||
extern TaskHandle_t loopTaskHandle;
|
||||
extern bool loopTaskWDTEnabled;
|
||||
|
||||
void enableLoopWDT() {
|
||||
if (loopTaskHandle != NULL) {
|
||||
if (esp_task_wdt_add(loopTaskHandle) != ESP_OK) {
|
||||
log_e("Failed to add loop task to WDT");
|
||||
} else {
|
||||
loopTaskWDTEnabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void disableLoopWDT() {
|
||||
if (loopTaskHandle != NULL && loopTaskWDTEnabled) {
|
||||
loopTaskWDTEnabled = false;
|
||||
if (esp_task_wdt_delete(loopTaskHandle) != ESP_OK) {
|
||||
log_e("Failed to remove loop task from WDT");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void feedLoopWDT() {
|
||||
esp_err_t err = esp_task_wdt_reset();
|
||||
if (err != ESP_OK) {
|
||||
log_e("Failed to feed WDT! Error: %d", err);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void enableCore0WDT() {
|
||||
TaskHandle_t idle_0 = xTaskGetIdleTaskHandleForCPU(0);
|
||||
if (idle_0 == NULL || esp_task_wdt_add(idle_0) != ESP_OK) {
|
||||
log_e("Failed to add Core 0 IDLE task to WDT");
|
||||
}
|
||||
}
|
||||
|
||||
void disableCore0WDT() {
|
||||
TaskHandle_t idle_0 = xTaskGetIdleTaskHandleForCPU(0);
|
||||
if (idle_0 == NULL || esp_task_wdt_delete(idle_0) != ESP_OK) {
|
||||
log_e("Failed to remove Core 0 IDLE task from WDT");
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef CONFIG_FREERTOS_UNICORE
|
||||
void enableCore1WDT() {
|
||||
TaskHandle_t idle_1 = xTaskGetIdleTaskHandleForCPU(1);
|
||||
if (idle_1 == NULL || esp_task_wdt_add(idle_1) != ESP_OK) {
|
||||
log_e("Failed to add Core 1 IDLE task to WDT");
|
||||
}
|
||||
}
|
||||
|
||||
void disableCore1WDT() {
|
||||
TaskHandle_t idle_1 = xTaskGetIdleTaskHandleForCPU(1);
|
||||
if (idle_1 == NULL || esp_task_wdt_delete(idle_1) != ESP_OK) {
|
||||
log_e("Failed to remove Core 1 IDLE task from WDT");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
BaseType_t xTaskCreateUniversal(
|
||||
TaskFunction_t pxTaskCode, const char *const pcName, const uint32_t usStackDepth, void *const pvParameters, UBaseType_t uxPriority,
|
||||
TaskHandle_t *const pxCreatedTask, const BaseType_t xCoreID
|
||||
) {
|
||||
#ifndef CONFIG_FREERTOS_UNICORE
|
||||
if (xCoreID >= 0 && xCoreID < 2) {
|
||||
return xTaskCreatePinnedToCore(pxTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask, xCoreID);
|
||||
} else {
|
||||
#endif
|
||||
return xTaskCreate(pxTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask);
|
||||
#ifndef CONFIG_FREERTOS_UNICORE
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
unsigned long ARDUINO_ISR_ATTR micros() {
|
||||
return (unsigned long)(esp_timer_get_time());
|
||||
}
|
||||
|
||||
unsigned long ARDUINO_ISR_ATTR millis() {
|
||||
return (unsigned long)(esp_timer_get_time() / 1000ULL);
|
||||
}
|
||||
|
||||
void delay(uint32_t ms) {
|
||||
vTaskDelay(ms / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
void ARDUINO_ISR_ATTR delayMicroseconds(uint32_t us) {
|
||||
uint64_t m = (uint64_t)esp_timer_get_time();
|
||||
if (us) {
|
||||
uint64_t e = (m + us);
|
||||
if (m > e) { //overflow
|
||||
while ((uint64_t)esp_timer_get_time() > e) {
|
||||
NOP();
|
||||
}
|
||||
}
|
||||
while ((uint64_t)esp_timer_get_time() < e) {
|
||||
NOP();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void initVariant() __attribute__((weak));
|
||||
void initVariant() {}
|
||||
|
||||
void init() __attribute__((weak));
|
||||
void init() {}
|
||||
|
||||
#ifdef CONFIG_APP_ROLLBACK_ENABLE
|
||||
bool verifyOta() __attribute__((weak));
|
||||
bool verifyOta() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool verifyRollbackLater() __attribute__((weak));
|
||||
bool verifyRollbackLater() {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BT_ENABLED
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
//overwritten in esp32-hal-bt.c
|
||||
bool btInUse() __attribute__((weak));
|
||||
bool btInUse() {
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
//from esp32-hal-bt.c
|
||||
extern bool btInUse();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void initArduino() {
|
||||
//init proper ref tick value for PLL (uncomment if REF_TICK is different than 1MHz)
|
||||
//ESP_REG(APB_CTRL_PLL_TICK_CONF_REG) = APB_CLK_FREQ / REF_CLK_FREQ - 1;
|
||||
#if CONFIG_SPIRAM_SUPPORT || CONFIG_SPIRAM
|
||||
psramInit();
|
||||
#endif
|
||||
#ifdef CONFIG_APP_ROLLBACK_ENABLE
|
||||
if (!verifyRollbackLater()) {
|
||||
const esp_partition_t *running = esp_ota_get_running_partition();
|
||||
esp_ota_img_states_t ota_state;
|
||||
if (esp_ota_get_state_partition(running, &ota_state) == ESP_OK) {
|
||||
if (ota_state == ESP_OTA_IMG_PENDING_VERIFY) {
|
||||
if (verifyOta()) {
|
||||
esp_ota_mark_app_valid_cancel_rollback();
|
||||
} else {
|
||||
log_e("OTA verification failed! Start rollback to the previous version ...");
|
||||
esp_ota_mark_app_invalid_rollback_and_reboot();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
esp_log_level_set("*", CONFIG_LOG_DEFAULT_LEVEL);
|
||||
esp_err_t err = nvs_flash_init();
|
||||
if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
|
||||
const esp_partition_t *partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, NULL);
|
||||
if (partition != NULL) {
|
||||
err = esp_partition_erase_range(partition, 0, partition->size);
|
||||
if (!err) {
|
||||
err = nvs_flash_init();
|
||||
} else {
|
||||
log_e("Failed to format the broken NVS partition!");
|
||||
}
|
||||
} else {
|
||||
log_e("Could not find NVS partition");
|
||||
}
|
||||
}
|
||||
if (err) {
|
||||
log_e("Failed to initialize NVS! Error: %u", err);
|
||||
}
|
||||
#ifdef CONFIG_BT_ENABLED
|
||||
if (!btInUse()) {
|
||||
esp_bt_controller_mem_release(ESP_BT_MODE_BTDM);
|
||||
}
|
||||
#endif
|
||||
init();
|
||||
initVariant();
|
||||
}
|
||||
|
||||
//used by hal log
|
||||
const char *ARDUINO_ISR_ATTR pathToFileName(const char *path) {
|
||||
size_t i = 0;
|
||||
size_t pos = 0;
|
||||
char *p = (char *)path;
|
||||
while (*p) {
|
||||
i++;
|
||||
if (*p == '/' || *p == '\\') {
|
||||
pos = i;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
return path + pos;
|
||||
}
|
||||
|
||||
#include "esp_rom_sys.h"
|
||||
#include "esp_debug_helpers.h"
|
||||
#if CONFIG_IDF_TARGET_ARCH_XTENSA
|
||||
#include "esp_cpu_utils.h"
|
||||
#else
|
||||
#include "riscv/rvruntime-frames.h"
|
||||
#endif
|
||||
#include "esp_memory_utils.h"
|
||||
#include "esp_private/panic_internal.h"
|
||||
|
||||
static arduino_panic_handler_t _panic_handler = NULL;
|
||||
static void *_panic_handler_arg = NULL;
|
||||
|
||||
void set_arduino_panic_handler(arduino_panic_handler_t handler, void *arg) {
|
||||
_panic_handler = handler;
|
||||
_panic_handler_arg = arg;
|
||||
}
|
||||
|
||||
arduino_panic_handler_t get_arduino_panic_handler(void) {
|
||||
return _panic_handler;
|
||||
}
|
||||
|
||||
void *get_arduino_panic_handler_arg(void) {
|
||||
return _panic_handler_arg;
|
||||
}
|
||||
|
||||
static void handle_custom_backtrace(panic_info_t *info) {
|
||||
arduino_panic_info_t p_info;
|
||||
p_info.reason = info->reason;
|
||||
p_info.core = info->core;
|
||||
p_info.pc = info->addr;
|
||||
p_info.backtrace_len = 0;
|
||||
p_info.backtrace_corrupt = false;
|
||||
p_info.backtrace_continues = false;
|
||||
|
||||
#if CONFIG_IDF_TARGET_ARCH_XTENSA
|
||||
XtExcFrame *xt_frame = (XtExcFrame *)info->frame;
|
||||
esp_backtrace_frame_t stk_frame = {.pc = xt_frame->pc, .sp = xt_frame->a1, .next_pc = xt_frame->a0, .exc_frame = xt_frame};
|
||||
uint32_t i = 100, pc_ptr = esp_cpu_process_stack_pc(stk_frame.pc);
|
||||
p_info.backtrace[p_info.backtrace_len++] = pc_ptr;
|
||||
|
||||
bool corrupted = !(esp_stack_ptr_is_sane(stk_frame.sp) && (esp_ptr_executable((void *)esp_cpu_process_stack_pc(stk_frame.pc)) ||
|
||||
/* Ignore the first corrupted PC in case of InstrFetchProhibited */
|
||||
(stk_frame.exc_frame && ((XtExcFrame *)stk_frame.exc_frame)->exccause == EXCCAUSE_INSTR_PROHIBITED)));
|
||||
|
||||
while (i-- > 0 && stk_frame.next_pc != 0 && !corrupted) {
|
||||
if (!esp_backtrace_get_next_frame(&stk_frame)) {
|
||||
corrupted = true;
|
||||
}
|
||||
pc_ptr = esp_cpu_process_stack_pc(stk_frame.pc);
|
||||
if (esp_ptr_executable((void *)pc_ptr)) {
|
||||
p_info.backtrace[p_info.backtrace_len++] = pc_ptr;
|
||||
if (p_info.backtrace_len == 60) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (corrupted) {
|
||||
p_info.backtrace_corrupt = true;
|
||||
} else if (stk_frame.next_pc != 0) {
|
||||
p_info.backtrace_continues = true;
|
||||
}
|
||||
#elif CONFIG_IDF_TARGET_ARCH_RISCV
|
||||
uint32_t sp = (uint32_t)((RvExcFrame *)info->frame)->sp;
|
||||
p_info.backtrace[p_info.backtrace_len++] = sp;
|
||||
uint32_t *spptr = (uint32_t *)(sp);
|
||||
for (int i = 0; i < 256; i++) {
|
||||
if (esp_ptr_executable((void *)spptr[i])) {
|
||||
p_info.backtrace[p_info.backtrace_len++] = spptr[i];
|
||||
if (p_info.backtrace_len == 60) {
|
||||
if (i < 255) {
|
||||
p_info.backtrace_continues = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
_panic_handler(&p_info, _panic_handler_arg);
|
||||
}
|
||||
|
||||
void __real_esp_panic_handler(panic_info_t *);
|
||||
void __wrap_esp_panic_handler(panic_info_t *info) {
|
||||
if (_panic_handler != NULL) {
|
||||
handle_custom_backtrace(info);
|
||||
}
|
||||
__real_esp_panic_handler(info);
|
||||
}
|
||||
|
|
@ -1,241 +0,0 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "esp32-hal-log.h"
|
||||
#include "esp32-hal-periman.h"
|
||||
#include "esp_bit_defs.h"
|
||||
|
||||
typedef struct ATTR_PACKED {
|
||||
peripheral_bus_type_t type;
|
||||
const char *extra_type;
|
||||
void *bus;
|
||||
int8_t bus_num;
|
||||
int8_t bus_channel;
|
||||
} peripheral_pin_item_t;
|
||||
|
||||
static peripheral_bus_deinit_cb_t deinit_functions[ESP32_BUS_TYPE_MAX];
|
||||
static peripheral_pin_item_t pins[SOC_GPIO_PIN_COUNT];
|
||||
|
||||
#define GPIO_NOT_VALID(p) ((p >= SOC_GPIO_PIN_COUNT) || ((SOC_GPIO_VALID_GPIO_MASK & (1ULL << p)) == 0))
|
||||
|
||||
const char *perimanGetTypeName(peripheral_bus_type_t type) {
|
||||
switch (type) {
|
||||
case ESP32_BUS_TYPE_INIT: return "INIT";
|
||||
case ESP32_BUS_TYPE_GPIO: return "GPIO";
|
||||
case ESP32_BUS_TYPE_UART_RX: return "UART_RX";
|
||||
case ESP32_BUS_TYPE_UART_TX: return "UART_TX";
|
||||
case ESP32_BUS_TYPE_UART_CTS: return "UART_CTS";
|
||||
case ESP32_BUS_TYPE_UART_RTS: return "UART_RTS";
|
||||
#if SOC_SDM_SUPPORTED
|
||||
case ESP32_BUS_TYPE_SIGMADELTA: return "SIGMADELTA";
|
||||
#endif
|
||||
#if SOC_ADC_SUPPORTED
|
||||
case ESP32_BUS_TYPE_ADC_ONESHOT: return "ADC_ONESHOT";
|
||||
case ESP32_BUS_TYPE_ADC_CONT: return "ADC_CONT";
|
||||
#endif
|
||||
#if SOC_DAC_SUPPORTED
|
||||
case ESP32_BUS_TYPE_DAC_ONESHOT: return "DAC_ONESHOT";
|
||||
case ESP32_BUS_TYPE_DAC_CONT: return "DAC_CONT";
|
||||
case ESP32_BUS_TYPE_DAC_COSINE: return "DAC_COSINE";
|
||||
#endif
|
||||
#if SOC_LEDC_SUPPORTED
|
||||
case ESP32_BUS_TYPE_LEDC: return "LEDC";
|
||||
#endif
|
||||
#if SOC_RMT_SUPPORTED
|
||||
case ESP32_BUS_TYPE_RMT_TX: return "RMT_TX";
|
||||
case ESP32_BUS_TYPE_RMT_RX: return "RMT_RX";
|
||||
#endif
|
||||
#if SOC_I2S_SUPPORTED
|
||||
case ESP32_BUS_TYPE_I2S_STD_MCLK: return "I2S_STD_MCLK";
|
||||
case ESP32_BUS_TYPE_I2S_STD_BCLK: return "I2S_STD_BCLK";
|
||||
case ESP32_BUS_TYPE_I2S_STD_WS: return "I2S_STD_WS";
|
||||
case ESP32_BUS_TYPE_I2S_STD_DOUT: return "I2S_STD_DOUT";
|
||||
case ESP32_BUS_TYPE_I2S_STD_DIN: return "I2S_STD_DIN";
|
||||
case ESP32_BUS_TYPE_I2S_TDM_MCLK: return "I2S_TDM_MCLK";
|
||||
case ESP32_BUS_TYPE_I2S_TDM_BCLK: return "I2S_TDM_BCLK";
|
||||
case ESP32_BUS_TYPE_I2S_TDM_WS: return "I2S_TDM_WS";
|
||||
case ESP32_BUS_TYPE_I2S_TDM_DOUT: return "I2S_TDM_DOUT";
|
||||
case ESP32_BUS_TYPE_I2S_TDM_DIN: return "I2S_TDM_DIN";
|
||||
case ESP32_BUS_TYPE_I2S_PDM_TX_CLK: return "I2S_PDM_TX_CLK";
|
||||
case ESP32_BUS_TYPE_I2S_PDM_TX_DOUT0: return "I2S_PDM_TX_DOUT0";
|
||||
case ESP32_BUS_TYPE_I2S_PDM_TX_DOUT1: return "I2S_PDM_TX_DOUT1";
|
||||
case ESP32_BUS_TYPE_I2S_PDM_RX_CLK: return "I2S_PDM_RX_CLK";
|
||||
case ESP32_BUS_TYPE_I2S_PDM_RX_DIN0: return "I2S_PDM_RX_DIN0";
|
||||
case ESP32_BUS_TYPE_I2S_PDM_RX_DIN1: return "I2S_PDM_RX_DIN1";
|
||||
case ESP32_BUS_TYPE_I2S_PDM_RX_DIN2: return "I2S_PDM_RX_DIN2";
|
||||
case ESP32_BUS_TYPE_I2S_PDM_RX_DIN3: return "I2S_PDM_RX_DIN3";
|
||||
#endif
|
||||
#if SOC_I2C_SUPPORTED
|
||||
case ESP32_BUS_TYPE_I2C_MASTER_SDA: return "I2C_MASTER_SDA";
|
||||
case ESP32_BUS_TYPE_I2C_MASTER_SCL: return "I2C_MASTER_SCL";
|
||||
case ESP32_BUS_TYPE_I2C_SLAVE_SDA: return "I2C_SLAVE_SDA";
|
||||
case ESP32_BUS_TYPE_I2C_SLAVE_SCL: return "I2C_SLAVE_SCL";
|
||||
#endif
|
||||
#if SOC_GPSPI_SUPPORTED
|
||||
case ESP32_BUS_TYPE_SPI_MASTER_SCK: return "SPI_MASTER_SCK";
|
||||
case ESP32_BUS_TYPE_SPI_MASTER_MISO: return "SPI_MASTER_MISO";
|
||||
case ESP32_BUS_TYPE_SPI_MASTER_MOSI: return "SPI_MASTER_MOSI";
|
||||
case ESP32_BUS_TYPE_SPI_MASTER_SS: return "SPI_MASTER_SS";
|
||||
#endif
|
||||
#if SOC_SDMMC_HOST_SUPPORTED
|
||||
case ESP32_BUS_TYPE_SDMMC_CLK: return "SDMMC_CLK";
|
||||
case ESP32_BUS_TYPE_SDMMC_CMD: return "SDMMC_CMD";
|
||||
case ESP32_BUS_TYPE_SDMMC_D0: return "SDMMC_D0";
|
||||
case ESP32_BUS_TYPE_SDMMC_D1: return "SDMMC_D1";
|
||||
case ESP32_BUS_TYPE_SDMMC_D2: return "SDMMC_D2";
|
||||
case ESP32_BUS_TYPE_SDMMC_D3: return "SDMMC_D3";
|
||||
#endif
|
||||
#if SOC_TOUCH_SENSOR_SUPPORTED
|
||||
case ESP32_BUS_TYPE_TOUCH: return "TOUCH";
|
||||
#endif
|
||||
#if SOC_USB_SERIAL_JTAG_SUPPORTED || SOC_USB_OTG_SUPPORTED
|
||||
case ESP32_BUS_TYPE_USB_DM: return "USB_DM";
|
||||
case ESP32_BUS_TYPE_USB_DP: return "USB_DP";
|
||||
#endif
|
||||
#if SOC_GPSPI_SUPPORTED
|
||||
case ESP32_BUS_TYPE_ETHERNET_SPI: return "ETHERNET_SPI";
|
||||
#endif
|
||||
#if CONFIG_ETH_USE_ESP32_EMAC
|
||||
case ESP32_BUS_TYPE_ETHERNET_RMII: return "ETHERNET_RMII";
|
||||
case ESP32_BUS_TYPE_ETHERNET_CLK: return "ETHERNET_CLK";
|
||||
case ESP32_BUS_TYPE_ETHERNET_MCD: return "ETHERNET_MCD";
|
||||
case ESP32_BUS_TYPE_ETHERNET_MDIO: return "ETHERNET_MDIO";
|
||||
case ESP32_BUS_TYPE_ETHERNET_PWR: return "ETHERNET_PWR";
|
||||
#endif
|
||||
#if CONFIG_LWIP_PPP_SUPPORT
|
||||
case ESP32_BUS_TYPE_PPP_TX: return "PPP_MODEM_TX";
|
||||
case ESP32_BUS_TYPE_PPP_RX: return "PPP_MODEM_RX";
|
||||
case ESP32_BUS_TYPE_PPP_RTS: return "PPP_MODEM_RTS";
|
||||
case ESP32_BUS_TYPE_PPP_CTS: return "PPP_MODEM_CTS";
|
||||
#endif
|
||||
default: return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
bool perimanSetPinBus(uint8_t pin, peripheral_bus_type_t type, void *bus, int8_t bus_num, int8_t bus_channel) {
|
||||
peripheral_bus_type_t otype = ESP32_BUS_TYPE_INIT;
|
||||
void *obus = NULL;
|
||||
if (GPIO_NOT_VALID(pin)) {
|
||||
log_e("Invalid pin: %u", pin);
|
||||
return false;
|
||||
}
|
||||
if (type >= ESP32_BUS_TYPE_MAX) {
|
||||
log_e("Invalid type: %s (%u) when setting pin %u", perimanGetTypeName(type), (unsigned int)type, pin);
|
||||
return false;
|
||||
}
|
||||
if (type > ESP32_BUS_TYPE_GPIO && bus == NULL) {
|
||||
log_e("Bus is NULL for pin %u with type %s (%u)", pin, perimanGetTypeName(type), (unsigned int)type);
|
||||
return false;
|
||||
}
|
||||
if (type == ESP32_BUS_TYPE_INIT && bus != NULL) {
|
||||
log_e("Can't set a Bus to INIT Type (pin %u)", pin);
|
||||
return false;
|
||||
}
|
||||
otype = pins[pin].type;
|
||||
obus = pins[pin].bus;
|
||||
if (type == otype && bus == obus) {
|
||||
if (type != ESP32_BUS_TYPE_INIT) {
|
||||
log_i("Pin %u already has type %s (%u) with bus %p", pin, perimanGetTypeName(type), (unsigned int)type, bus);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (obus != NULL) {
|
||||
if (deinit_functions[otype] == NULL) {
|
||||
log_e("No deinit function for type %s (%u) (pin %u)", perimanGetTypeName(otype), (unsigned int)otype, pin);
|
||||
return false;
|
||||
}
|
||||
if (!deinit_functions[otype](obus)) {
|
||||
log_e("Deinit function for previous bus type %s (%u) failed (pin %u)", perimanGetTypeName(otype), (unsigned int)otype, pin);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
pins[pin].type = type;
|
||||
pins[pin].bus = bus;
|
||||
pins[pin].bus_num = bus_num;
|
||||
pins[pin].bus_channel = bus_channel;
|
||||
pins[pin].extra_type = NULL;
|
||||
log_v("Pin %u successfully set to type %s (%u) with bus %p", pin, perimanGetTypeName(type), (unsigned int)type, bus);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool perimanSetPinBusExtraType(uint8_t pin, const char *extra_type) {
|
||||
if (GPIO_NOT_VALID(pin)) {
|
||||
log_e("Invalid pin: %u", pin);
|
||||
return false;
|
||||
}
|
||||
if (pins[pin].type == ESP32_BUS_TYPE_INIT) {
|
||||
log_e("Can't set extra type for Bus INIT Type (pin %u)", pin);
|
||||
return false;
|
||||
}
|
||||
pins[pin].extra_type = extra_type;
|
||||
log_v("Successfully set extra_type %s for pin %u", extra_type, pin);
|
||||
return true;
|
||||
}
|
||||
|
||||
void *perimanGetPinBus(uint8_t pin, peripheral_bus_type_t type) {
|
||||
if (GPIO_NOT_VALID(pin)) {
|
||||
log_e("Invalid pin: %u", pin);
|
||||
return NULL;
|
||||
}
|
||||
if (type >= ESP32_BUS_TYPE_MAX || type == ESP32_BUS_TYPE_INIT) {
|
||||
log_e("Invalid type %s (%u) for pin %u", perimanGetTypeName(type), (unsigned int)type, pin);
|
||||
return NULL;
|
||||
}
|
||||
if (pins[pin].type == type) {
|
||||
return pins[pin].bus;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
peripheral_bus_type_t perimanGetPinBusType(uint8_t pin) {
|
||||
if (GPIO_NOT_VALID(pin)) {
|
||||
log_e("Invalid pin: %u", pin);
|
||||
return ESP32_BUS_TYPE_MAX;
|
||||
}
|
||||
return pins[pin].type;
|
||||
}
|
||||
|
||||
const char *perimanGetPinBusExtraType(uint8_t pin) {
|
||||
if (GPIO_NOT_VALID(pin)) {
|
||||
log_e("Invalid pin: %u", pin);
|
||||
return NULL;
|
||||
}
|
||||
return pins[pin].extra_type;
|
||||
}
|
||||
|
||||
int8_t perimanGetPinBusNum(uint8_t pin) {
|
||||
if (GPIO_NOT_VALID(pin)) {
|
||||
log_e("Invalid pin: %u", pin);
|
||||
return -1;
|
||||
}
|
||||
return pins[pin].bus_num;
|
||||
}
|
||||
|
||||
int8_t perimanGetPinBusChannel(uint8_t pin) {
|
||||
if (GPIO_NOT_VALID(pin)) {
|
||||
log_e("Invalid pin: %u", pin);
|
||||
return -1;
|
||||
}
|
||||
return pins[pin].bus_channel;
|
||||
}
|
||||
|
||||
bool perimanSetBusDeinit(peripheral_bus_type_t type, peripheral_bus_deinit_cb_t cb) {
|
||||
if (type >= ESP32_BUS_TYPE_MAX || type == ESP32_BUS_TYPE_INIT) {
|
||||
log_e("Invalid type: %s (%u)", perimanGetTypeName(type), (unsigned int)type);
|
||||
return false;
|
||||
}
|
||||
if (cb == NULL) {
|
||||
log_e("Callback is NULL when setting deinit function for type %s (%u)", perimanGetTypeName(type), (unsigned int)type);
|
||||
return false;
|
||||
}
|
||||
deinit_functions[type] = cb;
|
||||
log_v("Deinit function for type %s (%u) successfully set to %p", perimanGetTypeName(type), (unsigned int)type, cb);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool perimanPinIsValid(uint8_t pin) {
|
||||
return !(GPIO_NOT_VALID(pin));
|
||||
}
|
||||
|
|
@ -1,148 +0,0 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "soc/soc_caps.h"
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define perimanClearPinBus(p) perimanSetPinBus(p, ESP32_BUS_TYPE_INIT, NULL, -1, -1)
|
||||
|
||||
typedef enum {
|
||||
ESP32_BUS_TYPE_INIT, // IO has not been attached to a bus yet
|
||||
ESP32_BUS_TYPE_GPIO, // IO is used as GPIO
|
||||
ESP32_BUS_TYPE_UART_RX, // IO is used as UART RX pin
|
||||
ESP32_BUS_TYPE_UART_TX, // IO is used as UART TX pin
|
||||
ESP32_BUS_TYPE_UART_CTS, // IO is used as UART CTS pin
|
||||
ESP32_BUS_TYPE_UART_RTS, // IO is used as UART RTS pin
|
||||
#if SOC_SDM_SUPPORTED
|
||||
ESP32_BUS_TYPE_SIGMADELTA, // IO is used as SigmeDelta output
|
||||
#endif
|
||||
#if SOC_ADC_SUPPORTED
|
||||
ESP32_BUS_TYPE_ADC_ONESHOT, // IO is used as ADC OneShot input
|
||||
ESP32_BUS_TYPE_ADC_CONT, // IO is used as ADC continuous input
|
||||
#endif
|
||||
#if SOC_DAC_SUPPORTED
|
||||
ESP32_BUS_TYPE_DAC_ONESHOT, // IO is used as DAC OneShot output
|
||||
ESP32_BUS_TYPE_DAC_CONT, // IO is used as DAC continuous output
|
||||
ESP32_BUS_TYPE_DAC_COSINE, // IO is used as DAC cosine output
|
||||
#endif
|
||||
#if SOC_LEDC_SUPPORTED
|
||||
ESP32_BUS_TYPE_LEDC, // IO is used as LEDC output
|
||||
#endif
|
||||
#if SOC_RMT_SUPPORTED
|
||||
ESP32_BUS_TYPE_RMT_TX, // IO is used as RMT output
|
||||
ESP32_BUS_TYPE_RMT_RX, // IO is used as RMT input
|
||||
#endif
|
||||
#if SOC_I2S_SUPPORTED
|
||||
ESP32_BUS_TYPE_I2S_STD_MCLK, // IO is used as I2S STD MCLK pin
|
||||
ESP32_BUS_TYPE_I2S_STD_BCLK, // IO is used as I2S STD BCLK pin
|
||||
ESP32_BUS_TYPE_I2S_STD_WS, // IO is used as I2S STD WS pin
|
||||
ESP32_BUS_TYPE_I2S_STD_DOUT, // IO is used as I2S STD DOUT pin
|
||||
ESP32_BUS_TYPE_I2S_STD_DIN, // IO is used as I2S STD DIN pin
|
||||
|
||||
ESP32_BUS_TYPE_I2S_TDM_MCLK, // IO is used as I2S TDM MCLK pin
|
||||
ESP32_BUS_TYPE_I2S_TDM_BCLK, // IO is used as I2S TDM BCLK pin
|
||||
ESP32_BUS_TYPE_I2S_TDM_WS, // IO is used as I2S TDM WS pin
|
||||
ESP32_BUS_TYPE_I2S_TDM_DOUT, // IO is used as I2S TDM DOUT pin
|
||||
ESP32_BUS_TYPE_I2S_TDM_DIN, // IO is used as I2S TDM DIN pin
|
||||
|
||||
ESP32_BUS_TYPE_I2S_PDM_TX_CLK, // IO is used as I2S PDM CLK pin
|
||||
ESP32_BUS_TYPE_I2S_PDM_TX_DOUT0, // IO is used as I2S PDM DOUT0 pin
|
||||
ESP32_BUS_TYPE_I2S_PDM_TX_DOUT1, // IO is used as I2S PDM DOUT1 pin
|
||||
|
||||
ESP32_BUS_TYPE_I2S_PDM_RX_CLK, // IO is used as I2S PDM CLK pin
|
||||
ESP32_BUS_TYPE_I2S_PDM_RX_DIN0, // IO is used as I2S PDM DIN0 pin
|
||||
ESP32_BUS_TYPE_I2S_PDM_RX_DIN1, // IO is used as I2S PDM DIN1 pin
|
||||
ESP32_BUS_TYPE_I2S_PDM_RX_DIN2, // IO is used as I2S PDM DIN2 pin
|
||||
ESP32_BUS_TYPE_I2S_PDM_RX_DIN3, // IO is used as I2S PDM DIN3 pin
|
||||
#endif
|
||||
#if SOC_I2C_SUPPORTED
|
||||
ESP32_BUS_TYPE_I2C_MASTER_SDA, // IO is used as I2C master SDA pin
|
||||
ESP32_BUS_TYPE_I2C_MASTER_SCL, // IO is used as I2C master SCL pin
|
||||
ESP32_BUS_TYPE_I2C_SLAVE_SDA, // IO is used as I2C slave SDA pin
|
||||
ESP32_BUS_TYPE_I2C_SLAVE_SCL, // IO is used as I2C slave SCL pin
|
||||
#endif
|
||||
#if SOC_GPSPI_SUPPORTED
|
||||
ESP32_BUS_TYPE_SPI_MASTER_SCK, // IO is used as SPI master SCK pin
|
||||
ESP32_BUS_TYPE_SPI_MASTER_MISO, // IO is used as SPI master MISO pin
|
||||
ESP32_BUS_TYPE_SPI_MASTER_MOSI, // IO is used as SPI master MOSI pin
|
||||
ESP32_BUS_TYPE_SPI_MASTER_SS, // IO is used as SPI master SS pin
|
||||
#endif
|
||||
#if SOC_SDMMC_HOST_SUPPORTED
|
||||
ESP32_BUS_TYPE_SDMMC_CLK, // IO is used as SDMMC CLK pin
|
||||
ESP32_BUS_TYPE_SDMMC_CMD, // IO is used as SDMMC CMD pin
|
||||
ESP32_BUS_TYPE_SDMMC_D0, // IO is used as SDMMC D0 pin
|
||||
ESP32_BUS_TYPE_SDMMC_D1, // IO is used as SDMMC D1 pin
|
||||
ESP32_BUS_TYPE_SDMMC_D2, // IO is used as SDMMC D2 pin
|
||||
ESP32_BUS_TYPE_SDMMC_D3, // IO is used as SDMMC D3 pin
|
||||
#endif
|
||||
#if SOC_TOUCH_SENSOR_SUPPORTED
|
||||
ESP32_BUS_TYPE_TOUCH, // IO is used as TOUCH pin
|
||||
#endif
|
||||
#if SOC_USB_SERIAL_JTAG_SUPPORTED || SOC_USB_OTG_SUPPORTED
|
||||
ESP32_BUS_TYPE_USB_DM, // IO is used as USB DM (+) pin
|
||||
ESP32_BUS_TYPE_USB_DP, // IO is used as USB DP (-) pin
|
||||
#endif
|
||||
#if SOC_GPSPI_SUPPORTED
|
||||
ESP32_BUS_TYPE_ETHERNET_SPI, // IO is used as ETHERNET SPI pin
|
||||
#endif
|
||||
#if CONFIG_ETH_USE_ESP32_EMAC
|
||||
ESP32_BUS_TYPE_ETHERNET_RMII, // IO is used as ETHERNET RMII pin
|
||||
ESP32_BUS_TYPE_ETHERNET_CLK, // IO is used as ETHERNET CLK pin
|
||||
ESP32_BUS_TYPE_ETHERNET_MCD, // IO is used as ETHERNET MCD pin
|
||||
ESP32_BUS_TYPE_ETHERNET_MDIO, // IO is used as ETHERNET MDIO pin
|
||||
ESP32_BUS_TYPE_ETHERNET_PWR, // IO is used as ETHERNET PWR pin
|
||||
#endif
|
||||
#if CONFIG_LWIP_PPP_SUPPORT
|
||||
ESP32_BUS_TYPE_PPP_TX, // IO is used as PPP Modem TX pin
|
||||
ESP32_BUS_TYPE_PPP_RX, // IO is used as PPP Modem RX pin
|
||||
ESP32_BUS_TYPE_PPP_RTS, // IO is used as PPP Modem RTS pin
|
||||
ESP32_BUS_TYPE_PPP_CTS, // IO is used as PPP Modem CTS pin
|
||||
#endif
|
||||
ESP32_BUS_TYPE_MAX
|
||||
} peripheral_bus_type_t;
|
||||
|
||||
typedef bool (*peripheral_bus_deinit_cb_t)(void *bus);
|
||||
|
||||
const char *perimanGetTypeName(peripheral_bus_type_t type);
|
||||
|
||||
// Sets the bus type, bus handle, bus number and bus channel for given pin.
|
||||
bool perimanSetPinBus(uint8_t pin, peripheral_bus_type_t type, void *bus, int8_t bus_num, int8_t bus_channel);
|
||||
|
||||
// Returns handle of the bus for the given pin if type of bus matches. NULL otherwise
|
||||
void *perimanGetPinBus(uint8_t pin, peripheral_bus_type_t type);
|
||||
|
||||
// Returns the type of the bus for the given pin if attached. ESP32_BUS_TYPE_MAX otherwise
|
||||
peripheral_bus_type_t perimanGetPinBusType(uint8_t pin);
|
||||
|
||||
// Returns the bus number or unit of the bus for the given pin if set. -1 otherwise
|
||||
int8_t perimanGetPinBusNum(uint8_t pin);
|
||||
|
||||
// Returns the bus channel of the bus for the given pin if set. -1 otherwise
|
||||
int8_t perimanGetPinBusChannel(uint8_t pin);
|
||||
|
||||
// Sets the peripheral destructor callback. Used to destroy bus when pin is assigned another function
|
||||
bool perimanSetBusDeinit(peripheral_bus_type_t type, peripheral_bus_deinit_cb_t cb);
|
||||
|
||||
// Check if given pin is a valid GPIO number
|
||||
bool perimanPinIsValid(uint8_t pin);
|
||||
|
||||
// Sets the extra type for non Init bus. Used to customize pin bus name which can be printed by printPerimanInfo().
|
||||
bool perimanSetPinBusExtraType(uint8_t pin, const char *extra_type);
|
||||
|
||||
// Returns the extra type of the bus for given pin if set. NULL otherwise
|
||||
const char *perimanGetPinBusExtraType(uint8_t pin);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// 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.
|
||||
|
||||
#ifndef _ESP32_HAL_PSRAM_H_
|
||||
#define _ESP32_HAL_PSRAM_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#ifndef BOARD_HAS_PSRAM
|
||||
#ifdef CONFIG_SPIRAM_SUPPORT
|
||||
#undef CONFIG_SPIRAM_SUPPORT
|
||||
#endif
|
||||
#ifdef CONFIG_SPIRAM
|
||||
#undef CONFIG_SPIRAM
|
||||
#endif
|
||||
#endif
|
||||
|
||||
bool psramInit();
|
||||
bool psramFound();
|
||||
|
||||
void *ps_malloc(size_t size);
|
||||
void *ps_calloc(size_t n, size_t size);
|
||||
void *ps_realloc(void *ptr, size_t size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ESP32_HAL_PSRAM_H_ */
|
||||
|
|
@ -1,236 +0,0 @@
|
|||
// Copyright 2023 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// 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.
|
||||
|
||||
#ifndef MAIN_ESP32_HAL_RMT_H_
|
||||
#define MAIN_ESP32_HAL_RMT_H_
|
||||
|
||||
#include "soc/soc_caps.h"
|
||||
#if SOC_RMT_SUPPORTED
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
RMT_RX_MODE = 0, // false
|
||||
RMT_TX_MODE = 1, // true
|
||||
} rmt_ch_dir_t;
|
||||
|
||||
typedef enum {
|
||||
RMT_MEM_NUM_BLOCKS_1 = 1,
|
||||
RMT_MEM_NUM_BLOCKS_2 = 2,
|
||||
#if SOC_RMT_TX_CANDIDATES_PER_GROUP > 2
|
||||
RMT_MEM_NUM_BLOCKS_3 = 3,
|
||||
RMT_MEM_NUM_BLOCKS_4 = 4,
|
||||
#if SOC_RMT_TX_CANDIDATES_PER_GROUP > 4
|
||||
RMT_MEM_NUM_BLOCKS_5 = 5,
|
||||
RMT_MEM_NUM_BLOCKS_6 = 6,
|
||||
RMT_MEM_NUM_BLOCKS_7 = 7,
|
||||
RMT_MEM_NUM_BLOCKS_8 = 8,
|
||||
#endif
|
||||
#endif
|
||||
} rmt_reserve_memsize_t;
|
||||
|
||||
// Each RMT Symbols has 4 bytes
|
||||
// Total number of bytes per RMT_MEM_BLOCK is RMT_SYMBOLS_PER_CHANNEL_BLOCK * 4 bytes
|
||||
typedef union {
|
||||
struct {
|
||||
uint32_t duration0 : 15;
|
||||
uint32_t level0 : 1;
|
||||
uint32_t duration1 : 15;
|
||||
uint32_t level1 : 1;
|
||||
};
|
||||
uint32_t val;
|
||||
} rmt_data_t;
|
||||
|
||||
// Reading and Writing shall use as rmt_symbols_size this unit
|
||||
// ESP32 has 8 MEM BLOCKS in total shared with Reading and/or Writing
|
||||
// ESP32-S2 has 4 MEM BLOCKS in total shared with Reading and/or Writing
|
||||
// ESP32-S3 has 4 MEM BLOCKS for Reading and another 4 MEM BLOCKS for Writing
|
||||
// ESP32-C3 has 2 MEM BLOCKS for Reading and another 2 MEM BLOCKS for Writing
|
||||
#define RMT_SYMBOLS_PER_CHANNEL_BLOCK SOC_RMT_MEM_WORDS_PER_CHANNEL
|
||||
|
||||
// Used to tell rmtRead() to wait for ever until reading data from the RMT channel
|
||||
#define RMT_WAIT_FOR_EVER ((uint32_t)portMAX_DELAY)
|
||||
|
||||
// Helper macro to calculate the number of RTM symbols in a array or type
|
||||
#define RMT_SYMBOLS_OF(x) (sizeof(x) / sizeof(rmt_data_t))
|
||||
|
||||
/**
|
||||
Initialize the object
|
||||
|
||||
New Parameters in Arduino Core 3: RMT tick is set in the rmtInit() function by the
|
||||
frequency of the RMT channel. Example: 100ns tick => 10MHz, thus frequency will be 10,000,000 Hz
|
||||
Returns <true> on execution success, <false> otherwise
|
||||
*/
|
||||
bool rmtInit(int pin, rmt_ch_dir_t channel_direction, rmt_reserve_memsize_t memsize, uint32_t frequency_Hz);
|
||||
|
||||
/**
|
||||
Sets the End of Transmission level to be set for the <pin> when the RMT transmission ends.
|
||||
This function affects how rmtWrite(), rmtWriteAsync() or rmtWriteLooping() will set the pin after writing the data.
|
||||
The default EOT level is LOW, in case this function isn't used before RMT Writing.
|
||||
This level can be set for each RMT pin and can be changed between writings to the same pin.
|
||||
|
||||
<EOT_Level> shall be Zero (LOW) or non-zero (HIGH) value.
|
||||
It only affects the transmission process, therefore, it doesn't affect any IDLE LEVEL before starting the RMT transmission.
|
||||
The pre-transmission idle level can be set manually calling, for instance, digitalWrite(pin, Level).
|
||||
|
||||
Returns <true> when EOT has been correctly set for <pin>, <false> otherwise.
|
||||
*/
|
||||
bool rmtSetEOT(int pin, uint8_t EOT_Level);
|
||||
|
||||
/**
|
||||
Sending data in Blocking Mode.
|
||||
<rmt_symbol> is a 32 bits structure as defined by rmt_data_t type.
|
||||
It is possible to use the macro RMT_SYMBOLS_OF(data), if data is an array of <rmt_data_t>.
|
||||
|
||||
Blocking mode - only returns after sending all data or by timeout.
|
||||
If the writing operation takes longer than <timeout_ms> in milliseconds, it will end its
|
||||
execution returning <false>.
|
||||
Timeout can be set as undefined time by passing <RMT_WAIT_FOR_EVER> as <timeout_ms> parameter.
|
||||
When the operation is timed out, rmtTransmitCompleted() will return <false> until the transmission
|
||||
is finished, when rmtTransmitCompleted() will return <true>.
|
||||
|
||||
Returns <true> when there is no error in the write operation, <false> otherwise, including when it
|
||||
exits by timeout.
|
||||
*/
|
||||
bool rmtWrite(int pin, rmt_data_t *data, size_t num_rmt_symbols, uint32_t timeout_ms);
|
||||
|
||||
/**
|
||||
Sending data in Async Mode.
|
||||
<rmt_symbol> is a 32 bits structure as defined by rmt_data_t type.
|
||||
It is possible to use the macro RMT_SYMBOLS_OF(data), if <data> is an array of <rmt_data_t>
|
||||
|
||||
If more than one rmtWriteAsync() is executed in sequence, it will wait for the first transmission
|
||||
to finish, resulting in a return <false> that indicates that the rmtWriteAsync() call has failed.
|
||||
In such case, this channel will have to finish the previous transmission before starting a new one.
|
||||
|
||||
Non-Blocking mode - returns right after execution.
|
||||
Returns <true> on execution success, <false> otherwise.
|
||||
|
||||
<bool rmtTransmitCompleted(int pin)> will return <true> when all data is sent.
|
||||
*/
|
||||
bool rmtWriteAsync(int pin, rmt_data_t *data, size_t num_rmt_symbols);
|
||||
|
||||
/**
|
||||
Writing data up to the reserved memsize, looping continuously
|
||||
<rmt_symbol> is a 32 bits structure as defined by rmt_data_t type.
|
||||
It is possible to use the macro RMT_SYMBOLS_OF(data), if data is an array of rmt_data_t
|
||||
|
||||
If *data or size_byte are NULL | Zero, it will disable the writing loop and stop transmission
|
||||
|
||||
Non-Blocking mode - returns right after execution
|
||||
Returns <true> on execution success, <false> otherwise
|
||||
|
||||
<bool rmtTransmitCompleted(int pin)> will return always <true> while it is looping.
|
||||
*/
|
||||
bool rmtWriteLooping(int pin, rmt_data_t *data, size_t num_rmt_symbols);
|
||||
|
||||
/**
|
||||
Checks if transmission is completed and the rmtChannel ready for transmitting new data.
|
||||
To be ready for a new transmission, means that the previous transmission is completed.
|
||||
Returns <true> when all data has been sent, <false> otherwise.
|
||||
The data transmission information is reset when a new rmtWrite/Async function is called.
|
||||
If rmtWrite() times out or rmtWriteAsync() is called, this function will return <false> until
|
||||
all data is sent out.
|
||||
rmtTranmitCompleted() will always return <true> when rmtWriteLooping() is called,
|
||||
because it has no effect in such case.
|
||||
*/
|
||||
bool rmtTransmitCompleted(int pin);
|
||||
|
||||
/**
|
||||
Initiates blocking receive. Read data will be stored in a user provided buffer <*data>
|
||||
It will read up to <num_rmt_symbols> RMT Symbols and the value of this variable will
|
||||
change to the effective number of symbols read.
|
||||
<rmt_symbol> is a 32 bits structure as defined by rmt_data_t type.
|
||||
|
||||
If the reading operation takes longer than <timeout_ms> in milliseconds, it will end its
|
||||
execution and the function will return <false>. In a time out scenario, <num_rmt_symbols> won't
|
||||
change and rmtReceiveCompleted() can be used latter to check if there is data available.
|
||||
Timeout can be set as undefined time by passing RMT_WAIT_FOR_EVER as <timeout_ms> parameter
|
||||
|
||||
Returns <true> when there is no error in the read operation, <false> otherwise, including when it
|
||||
exits by timeout.
|
||||
Returns, by value, the number of RMT Symbols read in <num_rmt_symbols> and the user buffer <data>
|
||||
when the read operation has success within the defined <timeout_ms>. If the function times out, it
|
||||
will read RMT data latter asynchronously, affecting <*data> and <*num_rmt_symbols>. After timeout,
|
||||
the application can check if data is already available using <rmtReceiveCompleted(int pin)>
|
||||
*/
|
||||
bool rmtRead(int pin, rmt_data_t *data, size_t *num_rmt_symbols, uint32_t timeout_ms);
|
||||
|
||||
/**
|
||||
Initiates async (non-blocking) receive. It will return immediately after execution.
|
||||
Read data will be stored in a user provided buffer <*data>.
|
||||
It will read up to <num_rmt_symbols> RMT Symbols and the value of this variable will
|
||||
change to the effective number of symbols read, whenever the read is completed.
|
||||
<rmt_symbol> is a 32 bits structure as defined by <rmt_data_t> type.
|
||||
|
||||
Returns <true> when there is no error in the read operation, <false> otherwise.
|
||||
Returns asynchronously, by value, the number of RMT Symbols read, and also, it will copy
|
||||
the RMT received data to the user buffer <data> when the read operation happens.
|
||||
The application can check if data is already available using <rmtReceiveCompleted(int pin)>
|
||||
*/
|
||||
bool rmtReadAsync(int pin, rmt_data_t *data, size_t *num_rmt_symbols);
|
||||
|
||||
/**
|
||||
Checks if a data reception is completed and the rmtChannel has new data for processing.
|
||||
Returns <true> when data has been received, <false> otherwise.
|
||||
The data reception information is reset when a new rmtRead/Async function is called.
|
||||
*/
|
||||
bool rmtReceiveCompleted(int pin);
|
||||
|
||||
/**
|
||||
Function used to set a threshold (in ticks) used to consider that a data reception has ended.
|
||||
In receive mode, when no edge is detected on the input signal for longer than idle_thres_ticks
|
||||
time, the receiving process is finished and the Data is made available by
|
||||
the rmtRead/Async functions. Note that this time (in RMT channel frequency cycles) will also
|
||||
define how many low/high bits are read at the end of the received data.
|
||||
The function returns <true> if it is correctly executed, <false> otherwise.
|
||||
*/
|
||||
bool rmtSetRxMaxThreshold(int pin, uint16_t idle_thres_ticks);
|
||||
|
||||
/**
|
||||
Parameters changed in Arduino Core 3: low and high (ticks) are now expressed in Carrier Freq in Hz and
|
||||
duty cycle in percentage float 0.0 to 1.0 - example: 38.5KHz 33% High => 38500, 0.33
|
||||
|
||||
Function to set a RX demodulation carrier or TX modulation carrier
|
||||
<carrier_en> is used to enable/disable the use of demodulation/modulation for RX/TX
|
||||
<carrier_level> true means that the polarity level for the (de)modulation is positive
|
||||
<frequency_Hz> is the carrier frequency used
|
||||
<duty_percent> is a float deom 0 to 1 (0.5 means a square wave) of the carrier frequency
|
||||
The function returns <true> if it is correctly executed, <false> otherwise.
|
||||
*/
|
||||
bool rmtSetCarrier(int pin, bool carrier_en, bool carrier_level, uint32_t frequency_Hz, float duty_percent);
|
||||
|
||||
/**
|
||||
Function used to filter input noise in the RX channel.
|
||||
In receiving mode, channel will ignore any input pulse which width (high or low)
|
||||
is smaller than <filter_pulse_ticks>
|
||||
If <filter_pulse_ns> is Zero, it will to disable the filter.
|
||||
The function returns <true> if it is correctly executed, <false> otherwise.
|
||||
*/
|
||||
bool rmtSetRxMinThreshold(int pin, uint8_t filter_pulse_ticks);
|
||||
|
||||
/**
|
||||
Deinitializes the driver and releases all allocated memory
|
||||
It also disables RMT for this gpio
|
||||
*/
|
||||
bool rmtDeinit(int pin);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SOC_RMT_SUPPORTED */
|
||||
#endif /* MAIN_ESP32_HAL_RMT_H_ */
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "soc/soc_caps.h"
|
||||
#if SOC_SDM_SUPPORTED
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
//freq 1220-312500 duty 0-255
|
||||
bool sigmaDeltaAttach(uint8_t pin, uint32_t freq);
|
||||
bool sigmaDeltaWrite(uint8_t pin, uint8_t duty);
|
||||
bool sigmaDeltaDetach(uint8_t pin);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SOC_SDM_SUPPORTED */
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,155 +0,0 @@
|
|||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// 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.
|
||||
|
||||
#ifndef MAIN_ESP32_HAL_SPI_H_
|
||||
#define MAIN_ESP32_HAL_SPI_H_
|
||||
|
||||
#include "soc/soc_caps.h"
|
||||
#if SOC_GPSPI_SUPPORTED
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define SPI_HAS_TRANSACTION
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
#define FSPI 0
|
||||
#define HSPI 1
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#define FSPI 1 //SPI 1 bus. ESP32S2: for external memory only (can use the same data lines but different SS)
|
||||
#define HSPI 2 //SPI 2 bus. ESP32S2: external memory or device - it can be matrixed to any pins
|
||||
#define SPI2 2 // Another name for ESP32S2 SPI 2
|
||||
#define SPI3 3 //SPI 3 bus. ESP32S2: device only - it can be matrixed to any pins
|
||||
#elif CONFIG_IDF_TARGET_ESP32
|
||||
#define FSPI 1 //SPI 1 bus attached to the flash (can use the same data lines but different SS)
|
||||
#define HSPI 2 //SPI 2 bus normally mapped to pins 12 - 15, but can be matrixed to any pins
|
||||
#define VSPI 3 //SPI 3 bus normally attached to pins 5, 18, 19 and 23, but can be matrixed to any pins
|
||||
#endif
|
||||
|
||||
// This defines are not representing the real Divider of the ESP32
|
||||
// the Defines match to an AVR Arduino on 16MHz for better compatibility
|
||||
#define SPI_CLOCK_DIV2 0x00101001 //8 MHz
|
||||
#define SPI_CLOCK_DIV4 0x00241001 //4 MHz
|
||||
#define SPI_CLOCK_DIV8 0x004c1001 //2 MHz
|
||||
#define SPI_CLOCK_DIV16 0x009c1001 //1 MHz
|
||||
#define SPI_CLOCK_DIV32 0x013c1001 //500 KHz
|
||||
#define SPI_CLOCK_DIV64 0x027c1001 //250 KHz
|
||||
#define SPI_CLOCK_DIV128 0x04fc1001 //125 KHz
|
||||
|
||||
#define SPI_MODE0 0
|
||||
#define SPI_MODE1 1
|
||||
#define SPI_MODE2 2
|
||||
#define SPI_MODE3 3
|
||||
|
||||
#define SPI_SS0 0
|
||||
#define SPI_SS1 1
|
||||
#define SPI_SS2 2
|
||||
#define SPI_SS_MASK_ALL 0x7
|
||||
|
||||
#define SPI_LSBFIRST 0
|
||||
#define SPI_MSBFIRST 1
|
||||
|
||||
struct spi_struct_t;
|
||||
typedef struct spi_struct_t spi_t;
|
||||
|
||||
spi_t *spiStartBus(uint8_t spi_num, uint32_t clockDiv, uint8_t dataMode, uint8_t bitOrder);
|
||||
void spiStopBus(spi_t *spi);
|
||||
|
||||
//Attach/Detach Signal Pins
|
||||
bool spiAttachSCK(spi_t *spi, int8_t sck);
|
||||
bool spiAttachMISO(spi_t *spi, int8_t miso);
|
||||
bool spiAttachMOSI(spi_t *spi, int8_t mosi);
|
||||
bool spiDetachSCK(spi_t *spi);
|
||||
bool spiDetachMISO(spi_t *spi);
|
||||
bool spiDetachMOSI(spi_t *spi);
|
||||
|
||||
//Attach/Detach SS pin to SPI_SSx signal
|
||||
bool spiAttachSS(spi_t *spi, uint8_t ss_num, int8_t ss);
|
||||
bool spiDetachSS(spi_t *spi);
|
||||
|
||||
//Enable/Disable SPI_SSx pins
|
||||
void spiEnableSSPins(spi_t *spi, uint8_t ss_mask);
|
||||
void spiDisableSSPins(spi_t *spi, uint8_t ss_mask);
|
||||
|
||||
//Enable/Disable hardware control of SPI_SSx pins
|
||||
void spiSSEnable(spi_t *spi);
|
||||
void spiSSDisable(spi_t *spi);
|
||||
|
||||
//Activate enabled SPI_SSx pins
|
||||
void spiSSSet(spi_t *spi);
|
||||
//Deactivate enabled SPI_SSx pins
|
||||
void spiSSClear(spi_t *spi);
|
||||
|
||||
void spiWaitReady(spi_t *spi);
|
||||
|
||||
uint32_t spiGetClockDiv(spi_t *spi);
|
||||
uint8_t spiGetDataMode(spi_t *spi);
|
||||
uint8_t spiGetBitOrder(spi_t *spi);
|
||||
|
||||
/*
|
||||
* Non transaction based lock methods (each locks and unlocks when called)
|
||||
* */
|
||||
void spiSetClockDiv(spi_t *spi, uint32_t clockDiv);
|
||||
void spiSetDataMode(spi_t *spi, uint8_t dataMode);
|
||||
void spiSetBitOrder(spi_t *spi, uint8_t bitOrder);
|
||||
|
||||
void spiWrite(spi_t *spi, const uint32_t *data, uint8_t len);
|
||||
void spiWriteByte(spi_t *spi, uint8_t data);
|
||||
void spiWriteWord(spi_t *spi, uint16_t data);
|
||||
void spiWriteLong(spi_t *spi, uint32_t data);
|
||||
|
||||
void spiTransfer(spi_t *spi, uint32_t *out, uint8_t len);
|
||||
uint8_t spiTransferByte(spi_t *spi, uint8_t data);
|
||||
uint16_t spiTransferWord(spi_t *spi, uint16_t data);
|
||||
uint32_t spiTransferLong(spi_t *spi, uint32_t data);
|
||||
void spiTransferBytes(spi_t *spi, const uint8_t *data, uint8_t *out, uint32_t size);
|
||||
void spiTransferBits(spi_t *spi, uint32_t data, uint32_t *out, uint8_t bits);
|
||||
|
||||
/*
|
||||
* New (EXPERIMENTAL) Transaction lock based API (lock once until endTransaction)
|
||||
* */
|
||||
void spiTransaction(spi_t *spi, uint32_t clockDiv, uint8_t dataMode, uint8_t bitOrder);
|
||||
void spiSimpleTransaction(spi_t *spi);
|
||||
void spiEndTransaction(spi_t *spi);
|
||||
|
||||
void spiWriteNL(spi_t *spi, const void *data_in, uint32_t len);
|
||||
void spiWriteByteNL(spi_t *spi, uint8_t data);
|
||||
void spiWriteShortNL(spi_t *spi, uint16_t data);
|
||||
void spiWriteLongNL(spi_t *spi, uint32_t data);
|
||||
void spiWritePixelsNL(spi_t *spi, const void *data_in, uint32_t len);
|
||||
|
||||
#define spiTransferNL(spi, data, len) spiTransferBytesNL(spi, data, data, len)
|
||||
uint8_t spiTransferByteNL(spi_t *spi, uint8_t data);
|
||||
uint16_t spiTransferShortNL(spi_t *spi, uint16_t data);
|
||||
uint32_t spiTransferLongNL(spi_t *spi, uint32_t data);
|
||||
void spiTransferBytesNL(spi_t *spi, const void *data_in, uint8_t *data_out, uint32_t len);
|
||||
void spiTransferBitsNL(spi_t *spi, uint32_t data_in, uint32_t *data_out, uint8_t bits);
|
||||
|
||||
/*
|
||||
* Helper functions to translate frequency to clock divider and back
|
||||
* */
|
||||
uint32_t spiFrequencyToClockDiv(uint32_t freq);
|
||||
uint32_t spiClockDivToFrequency(uint32_t freq);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SOC_GPSPI_SUPPORTED */
|
||||
#endif /* MAIN_ESP32_HAL_SPI_H_ */
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
/*
|
||||
Arduino.h - Main include file for the Arduino SDK
|
||||
Copyright (c) 2005-2013 Arduino Team. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "soc/soc_caps.h"
|
||||
#if SOC_GPTIMER_SUPPORTED
|
||||
|
||||
#include "esp32-hal.h"
|
||||
#include "driver/gptimer_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct timer_struct_t;
|
||||
typedef struct timer_struct_t hw_timer_t;
|
||||
|
||||
hw_timer_t *timerBegin(uint32_t frequency);
|
||||
void timerEnd(hw_timer_t *timer);
|
||||
|
||||
void timerStart(hw_timer_t *timer);
|
||||
void timerStop(hw_timer_t *timer);
|
||||
void timerRestart(hw_timer_t *timer);
|
||||
void timerWrite(hw_timer_t *timer, uint64_t val);
|
||||
|
||||
uint64_t timerRead(hw_timer_t *timer);
|
||||
uint64_t timerReadMicros(hw_timer_t *timer);
|
||||
uint64_t timerReadMilis(hw_timer_t *timer);
|
||||
double timerReadSeconds(hw_timer_t *timer);
|
||||
|
||||
uint32_t timerGetFrequency(hw_timer_t *timer);
|
||||
|
||||
void timerAttachInterrupt(hw_timer_t *timer, void (*userFunc)(void));
|
||||
void timerAttachInterruptArg(hw_timer_t *timer, void (*userFunc)(void *), void *arg);
|
||||
void timerDetachInterrupt(hw_timer_t *timer);
|
||||
|
||||
void timerAlarm(hw_timer_t *timer, uint64_t alarm_value, bool autoreload, uint64_t reload_count);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SOC_GPTIMER_SUPPORTED */
|
||||
|
|
@ -1,101 +0,0 @@
|
|||
/*
|
||||
Arduino.h - Main include file for the Arduino SDK
|
||||
Copyright (c) 2005-2013 Arduino Team. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef MAIN_ESP32_HAL_TOUCH_H_
|
||||
#define MAIN_ESP32_HAL_TOUCH_H_
|
||||
|
||||
#include "soc/soc_caps.h"
|
||||
#if SOC_TOUCH_SENSOR_SUPPORTED
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "esp32-hal.h"
|
||||
|
||||
#if !defined(SOC_TOUCH_VERSION_1) && !defined(SOC_TOUCH_VERSION_2)
|
||||
#error Touch IDF driver Not supported!
|
||||
#endif
|
||||
|
||||
#if SOC_TOUCH_VERSION_1 // ESP32
|
||||
typedef uint16_t touch_value_t;
|
||||
#elif SOC_TOUCH_VERSION_2 // ESP32S2 ESP32S3
|
||||
typedef uint32_t touch_value_t;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Set cycles that measurement operation takes
|
||||
* The result from touchRead, threshold and detection
|
||||
* accuracy depend on these values. Defaults are
|
||||
* 0x1000 for measure and 0x1000 for sleep.
|
||||
* With default values touchRead takes 0.5ms
|
||||
* */
|
||||
void touchSetCycles(uint16_t measure, uint16_t sleep);
|
||||
|
||||
/*
|
||||
* Read touch pad (for ESP32 values close to 0 mean touch detected /
|
||||
* for ESP32-S2/S3 higher values mean touch detected)
|
||||
* You can use this method to chose a good threshold value
|
||||
* to use as value for touchAttachInterrupt
|
||||
* */
|
||||
touch_value_t touchRead(uint8_t pin);
|
||||
|
||||
/*
|
||||
* Set function to be called if touch pad value falls (ESP32)
|
||||
* below the given threshold / rises (ESP32-S2/S3) by given increment (threshold).
|
||||
* Use touchRead to determine a proper threshold between touched and untouched state
|
||||
* */
|
||||
void touchAttachInterrupt(uint8_t pin, void (*userFunc)(void), touch_value_t threshold);
|
||||
void touchAttachInterruptArg(uint8_t pin, void (*userFunc)(void *), void *arg, touch_value_t threshold);
|
||||
void touchDetachInterrupt(uint8_t pin);
|
||||
|
||||
/*
|
||||
* Specific functions to ESP32
|
||||
* Tells the driver if it shall activate the ISR if the sensor is Lower or Higher than the Threshold
|
||||
* Default if Lower.
|
||||
**/
|
||||
|
||||
#if SOC_TOUCH_VERSION_1 // Only for ESP32 SoC
|
||||
void touchInterruptSetThresholdDirection(bool mustbeLower);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Specific functions to ESP32-S2 and ESP32-S3
|
||||
* Returns true when the latest ISR status for the Touchpad is that it is touched (Active)
|
||||
* and false when the Touchpad is untoouched (Inactive)
|
||||
* This function can be used in conjunction with ISR User callback in order to take action
|
||||
* as soon as the touchpad is touched and/or released
|
||||
**/
|
||||
|
||||
#if SOC_TOUCH_VERSION_2 // Only for ESP32S2 and ESP32S3
|
||||
// returns true if touch pad has been and continues pressed and false otherwise
|
||||
bool touchInterruptGetLastStatus(uint8_t pin);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Setup touch pad wake up from deep sleep with given threshold.
|
||||
**/
|
||||
void touchSleepWakeUpEnable(uint8_t pin, touch_value_t threshold);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SOC_TOUCH_SENSOR_SUPPORTED */
|
||||
#endif /* MAIN_ESP32_HAL_TOUCH_H_ */
|
||||
|
|
@ -1,123 +0,0 @@
|
|||
// Copyright 2015-2023 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// 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.
|
||||
|
||||
#ifndef MAIN_ESP32_HAL_UART_H_
|
||||
#define MAIN_ESP32_HAL_UART_H_
|
||||
|
||||
#include "soc/soc_caps.h"
|
||||
#if SOC_UART_SUPPORTED
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "hal/uart_types.h"
|
||||
|
||||
struct uart_struct_t;
|
||||
typedef struct uart_struct_t uart_t;
|
||||
|
||||
bool _testUartBegin(
|
||||
uint8_t uart_nr, uint32_t baudrate, uint32_t config, int8_t rxPin, int8_t txPin, uint32_t rx_buffer_size, uint32_t tx_buffer_size, bool inverted,
|
||||
uint8_t rxfifo_full_thrhd
|
||||
);
|
||||
uart_t *uartBegin(
|
||||
uint8_t uart_nr, uint32_t baudrate, uint32_t config, int8_t rxPin, int8_t txPin, uint32_t rx_buffer_size, uint32_t tx_buffer_size, bool inverted,
|
||||
uint8_t rxfifo_full_thrhd
|
||||
);
|
||||
void uartEnd(uint8_t uart_num);
|
||||
|
||||
// This is used to retrieve the Event Queue pointer from a UART IDF Driver in order to allow user to deal with its events
|
||||
void uartGetEventQueue(uart_t *uart, QueueHandle_t *q);
|
||||
|
||||
uint32_t uartAvailable(uart_t *uart);
|
||||
uint32_t uartAvailableForWrite(uart_t *uart);
|
||||
size_t uartReadBytes(uart_t *uart, uint8_t *buffer, size_t size, uint32_t timeout_ms);
|
||||
uint8_t uartRead(uart_t *uart);
|
||||
uint8_t uartPeek(uart_t *uart);
|
||||
|
||||
void uartWrite(uart_t *uart, uint8_t c);
|
||||
void uartWriteBuf(uart_t *uart, const uint8_t *data, size_t len);
|
||||
|
||||
void uartFlush(uart_t *uart);
|
||||
void uartFlushTxOnly(uart_t *uart, bool txOnly);
|
||||
|
||||
void uartSetBaudRate(uart_t *uart, uint32_t baud_rate);
|
||||
uint32_t uartGetBaudRate(uart_t *uart);
|
||||
|
||||
void uartSetRxInvert(uart_t *uart, bool invert);
|
||||
bool uartSetRxTimeout(uart_t *uart, uint8_t numSymbTimeout);
|
||||
bool uartSetRxFIFOFull(uart_t *uart, uint8_t numBytesFIFOFull);
|
||||
void uartSetFastReading(uart_t *uart);
|
||||
|
||||
void uartSetDebug(uart_t *uart);
|
||||
int uartGetDebug();
|
||||
|
||||
bool uartIsDriverInstalled(uart_t *uart);
|
||||
|
||||
// Negative Pin Number will keep it unmodified, thus this function can set individual pins
|
||||
// When pins are changed, it will detach the previous ones
|
||||
// Can be called before or after begin()
|
||||
bool uartSetPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin);
|
||||
|
||||
// helper functions
|
||||
int8_t uart_get_RxPin(uint8_t uart_num);
|
||||
int8_t uart_get_TxPin(uint8_t uart_num);
|
||||
void uart_init_PeriMan(void);
|
||||
|
||||
// Enables or disables HW Flow Control function -- needs also to set CTS and/or RTS pins
|
||||
// UART_HW_FLOWCTRL_DISABLE = 0x0 disable hardware flow control
|
||||
// UART_HW_FLOWCTRL_RTS = 0x1 enable RX hardware flow control (rts)
|
||||
// UART_HW_FLOWCTRL_CTS = 0x2 enable TX hardware flow control (cts)
|
||||
// UART_HW_FLOWCTRL_CTS_RTS = 0x3 enable hardware flow control
|
||||
bool uartSetHwFlowCtrlMode(uart_t *uart, uart_hw_flowcontrol_t mode, uint8_t threshold);
|
||||
|
||||
// Used to set RS485 function -- needs to disable HW Flow Control and set RTS pin to use
|
||||
// RTS pin becomes RS485 half duplex RE/DE
|
||||
// UART_MODE_UART = 0x00 mode: regular UART mode
|
||||
// UART_MODE_RS485_HALF_DUPLEX = 0x01 mode: half duplex RS485 UART mode control by RTS pin
|
||||
// UART_MODE_IRDA = 0x02 mode: IRDA UART mode
|
||||
// UART_MODE_RS485_COLLISION_DETECT = 0x03 mode: RS485 collision detection UART mode (used for test purposes)
|
||||
// UART_MODE_RS485_APP_CTRL = 0x04 mode: application control RS485 UART mode (used for test purposes)
|
||||
bool uartSetMode(uart_t *uart, uart_mode_t mode);
|
||||
|
||||
void uartStartDetectBaudrate(uart_t *uart);
|
||||
unsigned long uartDetectBaudrate(uart_t *uart);
|
||||
|
||||
/*
|
||||
These functions are for testing puspose only and can be used in Arduino Sketches
|
||||
Those are used in the UART examples
|
||||
*/
|
||||
|
||||
// Make sure UART's RX signal is connected to TX pin
|
||||
// This creates a loop that lets us receive anything we send on the UART
|
||||
void uart_internal_loopback(uint8_t uartNum, int8_t rxPin);
|
||||
|
||||
// Routines that generate BREAK in the UART for testing purpose
|
||||
|
||||
// Forces a BREAK in the line based on SERIAL_8N1 configuration at any baud rate
|
||||
void uart_send_break(uint8_t uartNum);
|
||||
// Sends a buffer and at the end of the stream, it generates BREAK in the line
|
||||
int uart_send_msg_with_break(uint8_t uartNum, uint8_t *msg, size_t msgSize);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SOC_UART_SUPPORTED */
|
||||
#endif /* MAIN_ESP32_HAL_UART_H_ */
|
||||
|
|
@ -1,157 +0,0 @@
|
|||
/*
|
||||
Arduino.h - Main include file for the Arduino SDK
|
||||
Copyright (c) 2005-2013 Arduino Team. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef HAL_ESP32_HAL_H_
|
||||
#define HAL_ESP32_HAL_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_sleep.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/event_groups.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef F_CPU
|
||||
#define F_CPU (CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ * 1000000U)
|
||||
#endif
|
||||
|
||||
#if CONFIG_ARDUINO_ISR_IRAM
|
||||
#define ARDUINO_ISR_ATTR IRAM_ATTR
|
||||
#define ARDUINO_ISR_FLAG ESP_INTR_FLAG_IRAM
|
||||
#else
|
||||
#define ARDUINO_ISR_ATTR
|
||||
#define ARDUINO_ISR_FLAG (0)
|
||||
#endif
|
||||
|
||||
#ifndef ARDUINO_RUNNING_CORE
|
||||
#define ARDUINO_RUNNING_CORE CONFIG_ARDUINO_RUNNING_CORE
|
||||
#endif
|
||||
|
||||
#ifndef ARDUINO_EVENT_RUNNING_CORE
|
||||
#define ARDUINO_EVENT_RUNNING_CORE CONFIG_ARDUINO_EVENT_RUNNING_CORE
|
||||
#endif
|
||||
|
||||
//forward declaration from freertos/portmacro.h
|
||||
void vPortYield(void);
|
||||
void yield(void);
|
||||
#define optimistic_yield(u)
|
||||
|
||||
#define ESP_REG(addr) *((volatile uint32_t *)(addr))
|
||||
#define NOP() asm volatile("nop")
|
||||
|
||||
#include "esp32-hal-log.h"
|
||||
#include "esp32-hal-matrix.h"
|
||||
#include "esp32-hal-uart.h"
|
||||
#include "esp32-hal-gpio.h"
|
||||
// #include "esp32-hal-touch.h"
|
||||
#include "esp32-hal-dac.h"
|
||||
#include "esp32-hal-adc.h"
|
||||
#include "esp32-hal-spi.h"
|
||||
#include "esp32-hal-i2c.h"
|
||||
#include "esp32-hal-ledc.h"
|
||||
#include "esp32-hal-rmt.h"
|
||||
#include "esp32-hal-sigmadelta.h"
|
||||
#include "esp32-hal-timer.h"
|
||||
#include "esp32-hal-bt.h"
|
||||
#include "esp32-hal-psram.h"
|
||||
//#include "esp32-hal-rgb-led.h"
|
||||
#include "esp32-hal-cpu.h"
|
||||
|
||||
void analogWrite(uint8_t pin, int value);
|
||||
void analogWriteFrequency(uint8_t pin, uint32_t freq);
|
||||
void analogWriteResolution(uint8_t pin, uint8_t bits);
|
||||
|
||||
//returns chip temperature in Celsius
|
||||
float temperatureRead();
|
||||
|
||||
//allows user to bypass SPI RAM test routine
|
||||
bool testSPIRAM(void);
|
||||
|
||||
#if CONFIG_AUTOSTART_ARDUINO
|
||||
//enable/disable WDT for Arduino's setup and loop functions
|
||||
void enableLoopWDT();
|
||||
void disableLoopWDT();
|
||||
//feed WDT for the loop task
|
||||
void feedLoopWDT();
|
||||
#endif
|
||||
|
||||
//enable/disable WDT for the IDLE task on Core 0 (SYSTEM)
|
||||
void enableCore0WDT();
|
||||
void disableCore0WDT();
|
||||
#ifndef CONFIG_FREERTOS_UNICORE
|
||||
//enable/disable WDT for the IDLE task on Core 1 (Arduino)
|
||||
void enableCore1WDT();
|
||||
void disableCore1WDT();
|
||||
#endif
|
||||
|
||||
//if xCoreID < 0 or CPU is unicore, it will use xTaskCreate, else xTaskCreatePinnedToCore
|
||||
//allows to easily handle all possible situations without repetitive code
|
||||
BaseType_t xTaskCreateUniversal(
|
||||
TaskFunction_t pxTaskCode, const char *const pcName, const uint32_t usStackDepth, void *const pvParameters, UBaseType_t uxPriority,
|
||||
TaskHandle_t *const pxCreatedTask, const BaseType_t xCoreID
|
||||
);
|
||||
|
||||
unsigned long micros();
|
||||
unsigned long millis();
|
||||
void delay(uint32_t);
|
||||
void delayMicroseconds(uint32_t us);
|
||||
|
||||
#if !CONFIG_ESP32_PHY_AUTO_INIT
|
||||
void arduino_phy_init();
|
||||
#endif
|
||||
|
||||
#if !CONFIG_AUTOSTART_ARDUINO
|
||||
void initArduino();
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
int core; // core which triggered panic
|
||||
const char *reason; // exception string
|
||||
const void *pc; // instruction address that triggered the exception
|
||||
bool backtrace_corrupt; // if backtrace is corrupt
|
||||
bool backtrace_continues; // if backtrace continues, but did not fit
|
||||
unsigned int backtrace_len; // number of backtrace addresses
|
||||
unsigned int backtrace[60]; // backtrace addresses array
|
||||
} arduino_panic_info_t;
|
||||
|
||||
typedef void (*arduino_panic_handler_t)(arduino_panic_info_t *info, void *arg);
|
||||
|
||||
void set_arduino_panic_handler(arduino_panic_handler_t handler, void *arg);
|
||||
arduino_panic_handler_t get_arduino_panic_handler(void);
|
||||
void *get_arduino_panic_handler_arg(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HAL_ESP32_HAL_H_ */
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
// esp8266-compat.h - Compatibility functions to help ESP8266 libraries and user code run on ESP32
|
||||
|
||||
// Copyright (c) 2017 Evandro Luis Copercini. All rights reserved.
|
||||
//
|
||||
// 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.
|
||||
|
||||
#ifndef _ESP8266_COMPAT_H_
|
||||
#define _ESP8266_COMPAT_H_
|
||||
|
||||
#define ICACHE_FLASH_ATTR
|
||||
#define ICACHE_RAM_ATTR ARDUINO_ISR_ATTR
|
||||
|
||||
#endif /* _ESP8266_COMPAT_H_ */
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// 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.
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Major version number (X.x.x) */
|
||||
#define ESP_ARDUINO_VERSION_MAJOR 3
|
||||
/** Minor version number (x.X.x) */
|
||||
#define ESP_ARDUINO_VERSION_MINOR 0
|
||||
/** Patch version number (x.x.X) */
|
||||
#define ESP_ARDUINO_VERSION_PATCH 4
|
||||
|
||||
/**
|
||||
* Macro to convert ARDUINO version number into an integer
|
||||
*
|
||||
* To be used in comparisons, such as ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(2, 0, 0)
|
||||
*/
|
||||
#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
|
||||
|
||||
/**
|
||||
* Current ARDUINO version, as an integer
|
||||
*
|
||||
* To be used in comparisons, such as ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(2, 0, 0)
|
||||
*/
|
||||
#define ESP_ARDUINO_VERSION ESP_ARDUINO_VERSION_VAL(ESP_ARDUINO_VERSION_MAJOR, ESP_ARDUINO_VERSION_MINOR, ESP_ARDUINO_VERSION_PATCH)
|
||||
|
||||
/**
|
||||
* Current ARDUINO version, as string
|
||||
*/
|
||||
#define df2xstr(s) #s
|
||||
#define df2str(s) df2xstr(s)
|
||||
#define ESP_ARDUINO_VERSION_STR df2str(ESP_ARDUINO_VERSION_MAJOR) "." df2str(ESP_ARDUINO_VERSION_MINOR) "." df2str(ESP_ARDUINO_VERSION_PATCH)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1,89 +0,0 @@
|
|||
/*
|
||||
Copyright (c) 2015 Hristo Gochkov. All rights reserved.
|
||||
This file is part of the RaspberryPi core for Arduino environment.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#ifndef PGMSPACE_INCLUDE
|
||||
#define PGMSPACE_INCLUDE
|
||||
|
||||
typedef void prog_void;
|
||||
typedef char prog_char;
|
||||
typedef unsigned char prog_uchar;
|
||||
typedef char prog_int8_t;
|
||||
typedef unsigned char prog_uint8_t;
|
||||
typedef short prog_int16_t;
|
||||
typedef unsigned short prog_uint16_t;
|
||||
typedef long prog_int32_t;
|
||||
typedef unsigned long prog_uint32_t;
|
||||
|
||||
#define PROGMEM
|
||||
#define PGM_P const char *
|
||||
#define PGM_VOID_P const void *
|
||||
#define PSTR(s) (s)
|
||||
#define _SFR_BYTE(n) (n)
|
||||
|
||||
#define pgm_read_byte(addr) (*(const unsigned char *)(addr))
|
||||
#define pgm_read_word(addr) ({ \
|
||||
typeof(addr) _addr = (addr); \
|
||||
*(const unsigned short *)(_addr); \
|
||||
})
|
||||
#define pgm_read_dword(addr) ({ \
|
||||
typeof(addr) _addr = (addr); \
|
||||
*(const unsigned long *)(_addr); \
|
||||
})
|
||||
#define pgm_read_float(addr) ({ \
|
||||
typeof(addr) _addr = (addr); \
|
||||
*(const float *)(_addr); \
|
||||
})
|
||||
#define pgm_read_ptr(addr) ({ \
|
||||
typeof(addr) _addr = (addr); \
|
||||
*(void * const *)(_addr); \
|
||||
})
|
||||
|
||||
#define pgm_get_far_address(x) ((uint32_t)(&(x)))
|
||||
|
||||
#define pgm_read_byte_near(addr) pgm_read_byte(addr)
|
||||
#define pgm_read_word_near(addr) pgm_read_word(addr)
|
||||
#define pgm_read_dword_near(addr) pgm_read_dword(addr)
|
||||
#define pgm_read_float_near(addr) pgm_read_float(addr)
|
||||
#define pgm_read_ptr_near(addr) pgm_read_ptr(addr)
|
||||
#define pgm_read_byte_far(addr) pgm_read_byte(addr)
|
||||
#define pgm_read_word_far(addr) pgm_read_word(addr)
|
||||
#define pgm_read_dword_far(addr) pgm_read_dword(addr)
|
||||
#define pgm_read_float_far(addr) pgm_read_float(addr)
|
||||
#define pgm_read_ptr_far(addr) pgm_read_ptr(addr)
|
||||
|
||||
#define memcmp_P memcmp
|
||||
#define memccpy_P memccpy
|
||||
#define memmem_P memmem
|
||||
#define memcpy_P memcpy
|
||||
#define strcpy_P strcpy
|
||||
#define strncpy_P strncpy
|
||||
#define strcat_P strcat
|
||||
#define strncat_P strncat
|
||||
#define strcmp_P strcmp
|
||||
#define strncmp_P strncmp
|
||||
#define strcasecmp_P strcasecmp
|
||||
#define strncasecmp_P strncasecmp
|
||||
#define strlen_P strlen
|
||||
#define strnlen_P strnlen
|
||||
#define strstr_P strstr
|
||||
#define printf_P printf
|
||||
#define sprintf_P sprintf
|
||||
#define snprintf_P snprintf
|
||||
#define vsnprintf_P vsnprintf
|
||||
|
||||
#endif
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
#ifndef Pins_Arduino_h
|
||||
#define Pins_Arduino_h
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define EXTERNAL_NUM_INTERRUPTS 16
|
||||
#define NUM_DIGITAL_PINS 40
|
||||
#define NUM_ANALOG_INPUTS 16
|
||||
|
||||
#define analogInputToDigitalPin(p) (((p)<20)?(esp32_adc2gpio[(p)]):-1)
|
||||
#define digitalPinToInterrupt(p) (((p)<40)?(p):-1)
|
||||
#define digitalPinHasPWM(p) (p < 34)
|
||||
|
||||
static const uint8_t TX = 1;
|
||||
static const uint8_t RX = 3;
|
||||
|
||||
static const uint8_t SDA = 21;
|
||||
static const uint8_t SCL = 22;
|
||||
|
||||
static const uint8_t SS = 5;
|
||||
static const uint8_t MOSI = 23;
|
||||
static const uint8_t MISO = 19;
|
||||
static const uint8_t SCK = 18;
|
||||
|
||||
static const uint8_t A0 = 36;
|
||||
static const uint8_t A3 = 39;
|
||||
static const uint8_t A4 = 32;
|
||||
static const uint8_t A5 = 33;
|
||||
static const uint8_t A6 = 34;
|
||||
static const uint8_t A7 = 35;
|
||||
static const uint8_t A10 = 4;
|
||||
static const uint8_t A11 = 0;
|
||||
static const uint8_t A12 = 2;
|
||||
static const uint8_t A13 = 15;
|
||||
static const uint8_t A14 = 13;
|
||||
static const uint8_t A15 = 12;
|
||||
static const uint8_t A16 = 14;
|
||||
static const uint8_t A17 = 27;
|
||||
static const uint8_t A18 = 25;
|
||||
static const uint8_t A19 = 26;
|
||||
|
||||
static const uint8_t T0 = 4;
|
||||
static const uint8_t T1 = 0;
|
||||
static const uint8_t T2 = 2;
|
||||
static const uint8_t T3 = 15;
|
||||
static const uint8_t T4 = 13;
|
||||
static const uint8_t T5 = 12;
|
||||
static const uint8_t T6 = 14;
|
||||
static const uint8_t T7 = 27;
|
||||
static const uint8_t T8 = 33;
|
||||
static const uint8_t T9 = 32;
|
||||
|
||||
static const uint8_t DAC1 = 25;
|
||||
static const uint8_t DAC2 = 26;
|
||||
|
||||
#endif /* Pins_Arduino_h */
|
||||
|
|
@ -1,98 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2014, RoboPeak
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* RoboPeak LIDAR System
|
||||
* Data Packet IO packet definition for RP-LIDAR
|
||||
*
|
||||
* Copyright 2009 - 2014 RoboPeak Team
|
||||
* http://www.robopeak.com
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "rplidar_protocol.h"
|
||||
|
||||
// Commands
|
||||
//-----------------------------------------
|
||||
|
||||
// Commands without payload and response
|
||||
#define RPLIDAR_CMD_STOP 0x25
|
||||
#define RPLIDAR_CMD_SCAN 0x20
|
||||
#define RPLIDAR_CMD_FORCE_SCAN 0x21
|
||||
#define RPLIDAR_CMD_RESET 0x40
|
||||
|
||||
|
||||
// Commands without payload but have response
|
||||
#define RPLIDAR_CMD_GET_DEVICE_INFO 0x50
|
||||
#define RPLIDAR_CMD_GET_DEVICE_HEALTH 0x52
|
||||
|
||||
#if defined(_WIN32)
|
||||
#pragma pack(1)
|
||||
#endif
|
||||
|
||||
|
||||
// Response
|
||||
// ------------------------------------------
|
||||
#define RPLIDAR_ANS_TYPE_MEASUREMENT 0x81
|
||||
|
||||
#define RPLIDAR_ANS_TYPE_DEVINFO 0x4
|
||||
#define RPLIDAR_ANS_TYPE_DEVHEALTH 0x6
|
||||
|
||||
|
||||
#define RPLIDAR_STATUS_OK 0x0
|
||||
#define RPLIDAR_STATUS_WARNING 0x1
|
||||
#define RPLIDAR_STATUS_ERROR 0x2
|
||||
|
||||
#define RPLIDAR_RESP_MEASUREMENT_SYNCBIT (0x1<<0)
|
||||
#define RPLIDAR_RESP_MEASUREMENT_QUALITY_SHIFT 2
|
||||
#define RPLIDAR_RESP_MEASUREMENT_CHECKBIT (0x1<<0)
|
||||
#define RPLIDAR_RESP_MEASUREMENT_ANGLE_SHIFT 1
|
||||
|
||||
typedef struct _rplidar_response_measurement_node_t {
|
||||
_u8 sync_quality; // syncbit:1;syncbit_inverse:1;quality:6;
|
||||
_u16 angle_q6_checkbit; // check_bit:1;angle_q6:15;
|
||||
_u16 distance_q2;
|
||||
} __attribute__((packed)) rplidar_response_measurement_node_t;
|
||||
|
||||
typedef struct _rplidar_response_device_info_t {
|
||||
_u8 model;
|
||||
_u16 firmware_version;
|
||||
_u8 hardware_version;
|
||||
_u8 serialnum[16];
|
||||
} __attribute__((packed)) rplidar_response_device_info_t;
|
||||
|
||||
typedef struct _rplidar_response_device_health_t {
|
||||
_u8 status;
|
||||
_u16 error_code;
|
||||
} __attribute__((packed)) rplidar_response_device_health_t;
|
||||
|
||||
#if defined(_WIN32)
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2014, RoboPeak
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* RoboPeak LIDAR System
|
||||
* Data Packet IO protocol definition for RP-LIDAR
|
||||
*
|
||||
* Copyright 2009 - 2014 RoboPeak Team
|
||||
* http://www.robopeak.com
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
// RP-Lidar Input Packets
|
||||
|
||||
#define RPLIDAR_CMD_SYNC_BYTE 0xA5
|
||||
#define RPLIDAR_CMDFLAG_HAS_PAYLOAD 0x80
|
||||
|
||||
|
||||
#define RPLIDAR_ANS_SYNC_BYTE1 0xA5
|
||||
#define RPLIDAR_ANS_SYNC_BYTE2 0x5A
|
||||
|
||||
#define RPLIDAR_ANS_PKTFLAG_LOOP 0x1
|
||||
|
||||
|
||||
#if defined(_WIN32)
|
||||
#pragma pack(1)
|
||||
#endif
|
||||
|
||||
typedef struct _rplidar_cmd_packet_t {
|
||||
_u8 syncByte; //must be RPLIDAR_CMD_SYNC_BYTE
|
||||
_u8 cmd_flag;
|
||||
_u8 size;
|
||||
_u8 data[0];
|
||||
} __attribute__((packed)) rplidar_cmd_packet_t;
|
||||
|
||||
|
||||
typedef struct _rplidar_ans_header_t {
|
||||
_u8 syncByte1; // must be RPLIDAR_ANS_SYNC_BYTE1
|
||||
_u8 syncByte2; // must be RPLIDAR_ANS_SYNC_BYTE2
|
||||
_u32 size:30;
|
||||
_u32 subType:2;
|
||||
_u8 type;
|
||||
} __attribute__((packed)) rplidar_ans_header_t;
|
||||
|
||||
#if defined(_WIN32)
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
|
@ -1,116 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2014, RoboPeak
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
||||
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* RoboPeak LIDAR System
|
||||
* Common Types definition
|
||||
*
|
||||
* Copyright 2009 - 2014 RoboPeak Team
|
||||
* http://www.robopeak.com
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
//fake stdint.h for VC only
|
||||
|
||||
typedef signed char int8_t;
|
||||
typedef unsigned char uint8_t;
|
||||
|
||||
typedef __int16 int16_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
|
||||
typedef __int32 int32_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
|
||||
typedef __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
|
||||
#else
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
//based on stdint.h
|
||||
typedef int8_t _s8;
|
||||
typedef uint8_t _u8;
|
||||
|
||||
typedef int16_t _s16;
|
||||
typedef uint16_t _u16;
|
||||
|
||||
typedef int32_t _s32;
|
||||
typedef uint32_t _u32;
|
||||
|
||||
typedef int64_t _s64;
|
||||
typedef uint64_t _u64;
|
||||
|
||||
#define __small_endian
|
||||
|
||||
#ifndef __GNUC__
|
||||
#define __attribute__(x)
|
||||
#endif
|
||||
|
||||
|
||||
// The _word_size_t uses actual data bus width of the current CPU
|
||||
#ifdef _AVR_
|
||||
typedef _u8 _word_size_t;
|
||||
#define THREAD_PROC
|
||||
#elif defined (WIN64)
|
||||
typedef _u64 _word_size_t;
|
||||
#define THREAD_PROC __stdcall
|
||||
#elif defined (WIN32)
|
||||
typedef _u32 _word_size_t;
|
||||
#define THREAD_PROC __stdcall
|
||||
#elif defined (__GNUC__)
|
||||
typedef unsigned long _word_size_t;
|
||||
#define THREAD_PROC
|
||||
#elif defined (__ICCARM__)
|
||||
typedef _u32 _word_size_t;
|
||||
#define THREAD_PROC
|
||||
#endif
|
||||
|
||||
|
||||
typedef uint32_t u_result;
|
||||
|
||||
#define RESULT_OK 0
|
||||
#define RESULT_FAIL_BIT 0x80000000
|
||||
#define RESULT_ALREADY_DONE 0x20
|
||||
#define RESULT_INVALID_DATA (0x8000 | RESULT_FAIL_BIT)
|
||||
#define RESULT_OPERATION_FAIL (0x8001 | RESULT_FAIL_BIT)
|
||||
#define RESULT_OPERATION_TIMEOUT (0x8002 | RESULT_FAIL_BIT)
|
||||
#define RESULT_OPERATION_STOP (0x8003 | RESULT_FAIL_BIT)
|
||||
#define RESULT_OPERATION_NOT_SUPPORT (0x8004 | RESULT_FAIL_BIT)
|
||||
#define RESULT_FORMAT_NOT_SUPPORT (0x8005 | RESULT_FAIL_BIT)
|
||||
#define RESULT_INSUFFICIENT_MEMORY (0x8006 | RESULT_FAIL_BIT)
|
||||
|
||||
#define IS_OK(x) ( ((x) & RESULT_FAIL_BIT) == 0 )
|
||||
#define IS_FAIL(x) ( ((x) & RESULT_FAIL_BIT) )
|
||||
|
||||
typedef _word_size_t (THREAD_PROC * thread_proc_t ) ( void * );
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
/*
|
||||
stdlib_noniso.h - nonstandard (but usefull) conversion functions
|
||||
|
||||
Copyright (c) 2014 Ivan Grokhotkov. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef STDLIB_NONISO_H
|
||||
#define STDLIB_NONISO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int atoi(const char *s);
|
||||
|
||||
long atol(const char* s);
|
||||
|
||||
double atof(const char* s);
|
||||
|
||||
char* itoa (int val, char *s, int radix);
|
||||
|
||||
char* ltoa (long val, char *s, int radix);
|
||||
|
||||
char* utoa (unsigned int val, char *s, int radix);
|
||||
|
||||
char* ultoa (unsigned long val, char *s, int radix);
|
||||
|
||||
char* dtostrf (double val, signed char width, unsigned char prec, char *s);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -52,27 +52,13 @@ set(COMPONENT_SRCS "espd.c pdmain.c \
|
|||
../pd/src/s_inter_gui.c \
|
||||
../wifi/wifi.c \
|
||||
../wifi/net.c \
|
||||
gyro.cpp \
|
||||
../arduino/SparkFun_BNO080_Arduino_Library.cpp \
|
||||
../arduino/SPI.cpp \
|
||||
../arduino/Print.cpp \
|
||||
../arduino/Wire.cpp \
|
||||
../arduino/Stream.cpp \
|
||||
../arduino/WString.cpp \
|
||||
../arduino/esp32-hal-misc.c \
|
||||
../arduino/esp32-hal-gpio.c \
|
||||
../arduino/esp32-hal-spi.c \
|
||||
../arduino/esp32-hal-i2c.c \
|
||||
../arduino/esp32-hal-i2c-slave.c \
|
||||
../arduino/esp32-hal-matrix.c \
|
||||
../arduino/esp32-hal-cpu.c \
|
||||
../arduino/esp32-hal-periman.c \
|
||||
")
|
||||
|
||||
|
||||
set(COMPONENT_ADD_INCLUDEDIRS ".")
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DPD -DHAVE_UNISTD_H -DHAVE_ALLOCA_H -DPD_HEADLESS -DPD_INTERNAL -DSYMTABHASHSIZE=512 -DSTUPID_SORT -DCOSTABLESIZE=512 -Wno-unused-variable -Wno-unused-but-set-variable -Wno-unused-function -Wno-format -Wno-stringop-truncation -Wno-unused-const-variable")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DPD -DHAVE_UNISTD_H -DHAVE_ALLOCA_H -DPD_HEADLESS -DPD_INTERNAL -DSYMTABHASHSIZE=512 -DSTUPID_SORT -Wno-unused-variable -Wno-unused-but-set-variable -Wno-unused-function -Wno-format -Wno-stringop-truncation -Wno-unused-const-variable")
|
||||
|
||||
# set(COMPONENT_ADD_CFLAGS "-DPD -DHAVE_UNISTD_H -DHAVE_ALLOCA_H -DPD_HEADLESS -DPD_INTERNAL -DSYMTABHASHSIZE=512 -DSTUPID_SORT -Wno-unused-variable -Wno-unused-but-set-variable -Wno-unused-function -Wno-format -Wno-stringop-truncation -Wno-unused-const-variable")
|
||||
|
||||
register_component()
|
||||
|
|
|
|||
23
main/espd.c
23
main/espd.c
|
|
@ -187,6 +187,7 @@ static void initdacs( void)
|
|||
}
|
||||
}
|
||||
#else /* OBSOLETEAPI */
|
||||
|
||||
static void initdacs( void)
|
||||
{
|
||||
|
||||
|
|
@ -347,9 +348,6 @@ void trymem(int foo);
|
|||
|
||||
void app_main(void)
|
||||
{
|
||||
#ifdef PD_USE_GYRO
|
||||
int have_gyro;
|
||||
#endif
|
||||
esp_log_level_set("*", ESP_LOG_WARN);
|
||||
esp_log_level_set(TAG, ESP_LOG_INFO);
|
||||
|
||||
|
|
@ -372,24 +370,23 @@ void app_main(void)
|
|||
console_init();
|
||||
#endif
|
||||
|
||||
#ifdef PD_USE_GYRO
|
||||
if (!(have_gyro = gyro_init()))
|
||||
ESP_LOGE(TAG, "gyro init failed");
|
||||
else ESP_LOGI(TAG, "gyro initialized");
|
||||
#endif
|
||||
|
||||
ESP_LOGI(TAG, "Pd is running");
|
||||
ESP_LOGI(TAG, "[ 2 ] now write some shit");
|
||||
|
||||
while (1)
|
||||
{
|
||||
/*
|
||||
int zz = 0;
|
||||
if (!((zz++)%1000))
|
||||
{
|
||||
trymem(5);
|
||||
ESP_LOGI(TAG, "tick");
|
||||
}
|
||||
*/
|
||||
pd_pollhost();
|
||||
pdmain_tick();
|
||||
senddacs();
|
||||
#ifdef PD_USE_WIFI
|
||||
net_alive();
|
||||
#endif
|
||||
#ifdef PD_USE_GYRO
|
||||
gyro_poll();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
|||
15
main/espd.h
15
main/espd.h
|
|
@ -1,14 +1,10 @@
|
|||
#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* #define PD_USE_BLUETOOTH */ /* messages to Pd over bluetooth */
|
||||
#define PD_USE_WIFI /* messages to/from Pd over wifi TCP */
|
||||
#define PD_USE_CONSOLE /* messages to Pd over "console" (USB serial) */
|
||||
/* #define PD_INCLUDEPATCH */ /* load the patch defined in "testpatch.c" */
|
||||
/* #define PD_LYRAT */ /* using LyraT or LyraT mini board */
|
||||
#define USEADC /* enable audio input (output always enabled) */
|
||||
#define PD_USE_GYRO /* complex Arts board with BNO085 gyro */
|
||||
/* #define PD_USE_GYRO */ /* complex Arts board with BNO085 gyro */
|
||||
#define IOCHANS 2
|
||||
#define OBSOLETEAPI /* need this for LyraT boards */
|
||||
|
||||
|
|
@ -53,12 +49,3 @@ extern char wifi_ipaddr[];
|
|||
#define PIN_DATA_OUT 32 /* data out from ESP32 to DAC */
|
||||
#define PIN_DATA_IN 35 /* data in from ADC to ESP32 */
|
||||
#endif /* PIN_BIT_CLOCK */
|
||||
|
||||
#ifdef PD_USE_GYRO
|
||||
#include "gyro.h"
|
||||
void pd_sendgyro(float roll, float pitch, float yaw);
|
||||
#endif
|
||||
|
||||
#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,60 +0,0 @@
|
|||
/* use SparkFun BNO080 library (which uses stuff from Arduino) to get
|
||||
orientation of Complex Arts Sensorboard */
|
||||
|
||||
#include "../arduino/SparkFun_BNO080_Arduino_Library.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "gyro.h"
|
||||
#include "espd.h"
|
||||
|
||||
#ifdef PD_USE_GYRO
|
||||
|
||||
/* IMU device */
|
||||
BNO080 myIMU;
|
||||
|
||||
/* SPI device */
|
||||
SPIClass spiPort;
|
||||
uint32_t spiPortSpeed = 100*1000;
|
||||
|
||||
/* IMU pins */
|
||||
byte imuCSPin = PIN_IMUCSP;
|
||||
byte imuWAKPin = PIN_IMUWAK;
|
||||
byte imuINTPin = PIN_IMUINT;
|
||||
byte imuRSTPin = PIN_IMURST;
|
||||
|
||||
/* SPI pins */
|
||||
byte spiCLK = PIN_SPICLK;
|
||||
byte spiMISO = PIN_SPIMISO;
|
||||
byte spiMOSI = PIN_SPIMOSI;
|
||||
|
||||
char TAG[] = "gyro";
|
||||
|
||||
extern "C" void gyro_poll(void)
|
||||
{
|
||||
if (myIMU.dataAvailable() == true)
|
||||
{
|
||||
/* pd_sendgyro( myIMU.getRoll(), myIMU.getPitch(), myIMU.getYaw()); */
|
||||
pd_sendgyro(myIMU.getAccelX(), myIMU.getAccelY(), myIMU.getAccelZ());
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" int gyro_init(void)
|
||||
{
|
||||
/* initialize SPI interface for the BNO085 */
|
||||
spiPort.begin(spiCLK, spiMISO, spiMOSI, imuCSPin);
|
||||
|
||||
/* initialize IMU */
|
||||
if (myIMU.beginSPI(imuCSPin, imuWAKPin, imuINTPin, imuRSTPin,
|
||||
spiPortSpeed, spiPort) == false)
|
||||
return (0);
|
||||
|
||||
/* enable "rotation vector", readings will be produced every 50 ms */
|
||||
/* myIMU.enableRotationVector(50); */
|
||||
|
||||
/* enable accelerometer */
|
||||
myIMU.enableAccelerometer(50);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
#endif /* PD_USEGYRO */
|
||||
10
main/gyro.h
10
main/gyro.h
|
|
@ -1,10 +0,0 @@
|
|||
#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int gyro_init(void);
|
||||
void gyro_poll(void);
|
||||
|
||||
#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
|
@ -99,18 +99,6 @@ void pdmain_init( void)
|
|||
#endif
|
||||
}
|
||||
|
||||
#ifdef PD_USE_GYRO
|
||||
void pd_sendgyro(float roll, float pitch, float yaw)
|
||||
{
|
||||
t_atom at[3];
|
||||
SETFLOAT(at, roll);
|
||||
SETFLOAT(at+1, pitch);
|
||||
SETFLOAT(at+2, yaw);
|
||||
if (gensym("gyro")->s_thing)
|
||||
pd_list(gensym("gyro")->s_thing, 0, 3, at);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void pdmain_tick( void)
|
||||
{
|
||||
|
|
|
|||
1473
sdkconfig.wroom
1473
sdkconfig.wroom
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue