Compare commits

...

10 Commits

36 changed files with 227 additions and 5235 deletions

View File

@ -1,25 +1,9 @@
set(CORE_SRCS
cores/esp32/esp32-hal-adc.c
cores/esp32/esp32-hal-cpu.c
cores/esp32/esp32-hal-dac.c
cores/esp32/esp32-hal-gpio.c
cores/esp32/esp32-hal-i2c.c
cores/esp32/esp32-hal-ledc.c
cores/esp32/esp32-hal-matrix.c
cores/esp32/esp32-hal-misc.c
cores/esp32/esp32-hal-psram.c
cores/esp32/esp32-hal-sigmadelta.c
cores/esp32/esp32-hal-spi.c
cores/esp32/esp32-hal-tinyusb.c
cores/esp32/esp32-hal-touch.c
cores/esp32/esp32-hal-rmt.c
cores/esp32/FunctionalInterrupt.cpp
cores/esp32/stdlib_noniso.c
cores/esp32/USB.cpp
cores/esp32/USBCDC.cpp
cores/esp32/wiring_pulse.c
cores/esp32/wiring_shift.c
cores/esp32/WMath.cpp
)
set(LIBRARY_SRCS
@ -36,10 +20,11 @@ set(includedirs
)
set(srcs ${CORE_SRCS} ${LIBRARY_SRCS} ${BLE_SRCS})
set(requires spi_flash mbedtls esp_adc_cal wifi_provisioning)
set(priv_requires nvs_flash bootloader_support tinyusb espcpputils fmt)
set(requires spi_flash mbedtls wifi_provisioning driver)
set(priv_requires nvs_flash bootloader_support espcpputils goefmt)
idf_component_register(INCLUDE_DIRS ${includedirs} PRIV_INCLUDE_DIRS ${priv_includes} SRCS ${srcs} REQUIRES ${requires} PRIV_REQUIRES ${priv_requires})
set_property(TARGET ${COMPONENT_LIB} PROPERTY CXX_STANDARD 23)
if(IDF_TARGET STREQUAL "esp32")
target_compile_options(${COMPONENT_TARGET} PUBLIC -DARDUINO=10812 -DARDUINO_ESP32_DEV -DARDUINO_ARCH_ESP32 -DARDUINO_BOARD="ESP32_DEV" -DARDUINO_VARIANT="esp32" -DESP32)

View File

@ -1,44 +0,0 @@
/*
* FunctionalInterrupt.cpp
*
* Created on: 8 jul. 2018
* Author: Herman
*/
#include "FunctionalInterrupt.h"
#include "esp32-hal.h"
typedef void (*voidFuncPtr)(void);
typedef void (*voidFuncPtrArg)(void*);
extern "C"
{
extern void __attachInterruptFunctionalArg(uint8_t pin, voidFuncPtrArg userFunc, void * arg, int intr_type, bool functional);
}
void ARDUINO_ISR_ATTR interruptFunctional(void* arg)
{
InterruptArgStructure* localArg = (InterruptArgStructure*)arg;
if (localArg->interruptFunction)
{
localArg->interruptFunction();
}
}
void attachInterrupt(uint8_t pin, std::function<void(void)> intRoutine, int mode)
{
// use the local interrupt routine which takes the ArgStructure as argument
__attachInterruptFunctionalArg (pin, (voidFuncPtrArg)interruptFunctional, new InterruptArgStructure{intRoutine}, mode, true);
}
extern "C"
{
void cleanupFunctional(void* arg)
{
delete (InterruptArgStructure*)arg;
}
}

View File

@ -1,20 +0,0 @@
/*
* FunctionalInterrupt.h
*
* Created on: 8 jul. 2018
* Author: Herman
*/
#ifndef CORE_CORE_FUNCTIONALINTERRUPT_H_
#define CORE_CORE_FUNCTIONALINTERRUPT_H_
#include <functional>
struct InterruptArgStructure {
std::function<void(void)> interruptFunction;
};
void attachInterrupt(uint8_t pin, std::function<void(void)> intRoutine, int mode);
#endif /* CORE_CORE_FUNCTIONALINTERRUPT_H_ */

View File

@ -1,338 +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 "esp32-hal.h"
#include "esp32-hal-tinyusb.h"
#include "USB.h"
#if CONFIG_USB_ENABLED
#ifndef USB_VID
#define USB_VID USB_ESPRESSIF_VID
#endif
#ifndef USB_PID
#define USB_PID 0x0002
#endif
#ifndef USB_MANUFACTURER
#define USB_MANUFACTURER "Espressif Systems"
#endif
#ifndef USB_PRODUCT
#define USB_PRODUCT ARDUINO_BOARD
#endif
#ifndef USB_SERIAL
#define USB_SERIAL "0"
#endif
extern "C" {
#include "tinyusb.h"
}
#if CFG_TUD_DFU_RT
static uint16_t load_dfu_descriptor(uint8_t * dst, uint8_t * itf)
{
#define DFU_ATTR_CAN_DOWNLOAD 1
#define DFU_ATTR_CAN_UPLOAD 2
#define DFU_ATTR_MANIFESTATION_TOLERANT 4
#define DFU_ATTR_WILL_DETACH 8
#define DFU_ATTRS (DFU_ATTR_CAN_DOWNLOAD | DFU_ATTR_CAN_UPLOAD | DFU_ATTR_MANIFESTATION_TOLERANT)
uint8_t str_index = tinyusb_add_string_descriptor("TinyUSB DFU_RT");
uint8_t descriptor[TUD_DFU_RT_DESC_LEN] = {
// Interface number, string index, attributes, detach timeout, transfer size */
TUD_DFU_RT_DESCRIPTOR(*itf, str_index, DFU_ATTRS, 700, 64)
};
*itf+=1;
memcpy(dst, descriptor, TUD_DFU_RT_DESC_LEN);
return TUD_DFU_RT_DESC_LEN;
}
// Invoked on DFU_DETACH request to reboot to the bootloader
void tud_dfu_rt_reboot_to_dfu(void)
{
usb_persist_restart(RESTART_BOOTLOADER_DFU);
}
#endif /* CFG_TUD_DFU_RT */
ESP_EVENT_DEFINE_BASE(ARDUINO_USB_EVENTS);
static esp_event_loop_handle_t arduino_usb_event_loop_handle = NULL;
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){
if(arduino_usb_event_loop_handle == NULL){
return ESP_FAIL;
}
return esp_event_post_to(arduino_usb_event_loop_handle, event_base, event_id, event_data, event_data_size, 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){
if(arduino_usb_event_loop_handle == NULL){
return ESP_FAIL;
}
return esp_event_handler_register_with(arduino_usb_event_loop_handle, event_base, event_id, event_handler, event_handler_arg);
}
static bool tinyusb_device_mounted = false;
static bool tinyusb_device_suspended = false;
// Invoked when device is mounted (configured)
void tud_mount_cb(void){
tinyusb_device_mounted = true;
arduino_usb_event_data_t p = {0};
arduino_usb_event_post(ARDUINO_USB_EVENTS, ARDUINO_USB_STARTED_EVENT, &p, sizeof(arduino_usb_event_data_t), portMAX_DELAY);
}
// Invoked when device is unmounted
void tud_umount_cb(void){
tinyusb_device_mounted = false;
arduino_usb_event_data_t p = {0};
arduino_usb_event_post(ARDUINO_USB_EVENTS, ARDUINO_USB_STOPPED_EVENT, &p, sizeof(arduino_usb_event_data_t), portMAX_DELAY);
}
// Invoked when usb bus is suspended
// Within 7ms, device must draw an average of current less than 2.5 mA from bus
void tud_suspend_cb(bool remote_wakeup_en){
tinyusb_device_suspended = true;
arduino_usb_event_data_t p = {0};
p.suspend.remote_wakeup_en = remote_wakeup_en;
arduino_usb_event_post(ARDUINO_USB_EVENTS, ARDUINO_USB_SUSPEND_EVENT, &p, sizeof(arduino_usb_event_data_t), portMAX_DELAY);
}
// Invoked when usb bus is resumed
void tud_resume_cb(void){
tinyusb_device_suspended = false;
arduino_usb_event_data_t p = {0};
arduino_usb_event_post(ARDUINO_USB_EVENTS, ARDUINO_USB_RESUME_EVENT, &p, sizeof(arduino_usb_event_data_t), portMAX_DELAY);
}
ESPUSB::ESPUSB(size_t task_stack_size, uint8_t event_task_priority)
:vid(USB_VID)
,pid(USB_PID)
,product_name(USB_PRODUCT)
,manufacturer_name(USB_MANUFACTURER)
,serial_number(USB_SERIAL)
,fw_version(0x0100)
,usb_version(0x0200)// at least 2.1 or 3.x for BOS & webUSB
,usb_class(TUSB_CLASS_MISC)
,usb_subclass(MISC_SUBCLASS_COMMON)
,usb_protocol(MISC_PROTOCOL_IAD)
,usb_attributes(TUSB_DESC_CONFIG_ATT_SELF_POWERED)
,usb_power_ma(500)
,webusb_enabled(false)
,webusb_url("espressif.github.io/arduino-esp32/webusb.html")
,_started(false)
,_task_stack_size(task_stack_size)
,_event_task_priority(event_task_priority)
{
if (!arduino_usb_event_loop_handle) {
esp_event_loop_args_t event_task_args = {
.queue_size = 5,
.task_name = "arduino_usb_events",
.task_priority = _event_task_priority,
.task_stack_size = _task_stack_size,
.task_core_id = tskNO_AFFINITY
};
if (esp_event_loop_create(&event_task_args, &arduino_usb_event_loop_handle) != ESP_OK) {
log_e("esp_event_loop_create failed");
}
}
}
ESPUSB::~ESPUSB(){
if (arduino_usb_event_loop_handle) {
esp_event_loop_delete(arduino_usb_event_loop_handle);
arduino_usb_event_loop_handle = NULL;
}
}
bool ESPUSB::begin(){
if(!_started){
tinyusb_device_config_t tinyusb_device_config = {
.vid = vid,
.pid = pid,
.product_name = product_name.c_str(),
.manufacturer_name = manufacturer_name.c_str(),
.serial_number = serial_number.c_str(),
.fw_version = fw_version,
.usb_version = usb_version,
.usb_class = usb_class,
.usb_subclass = usb_subclass,
.usb_protocol = usb_protocol,
.usb_attributes = usb_attributes,
.usb_power_ma = usb_power_ma,
.webusb_enabled = webusb_enabled,
.webusb_url = webusb_url.c_str()
};
_started = tinyusb_init(&tinyusb_device_config) == ESP_OK;
}
return _started;
}
void ESPUSB::onEvent(esp_event_handler_t callback){
onEvent(ARDUINO_USB_ANY_EVENT, callback);
}
void ESPUSB::onEvent(arduino_usb_event_t event, esp_event_handler_t callback){
arduino_usb_event_handler_register_with(ARDUINO_USB_EVENTS, event, callback, this);
}
ESPUSB::operator bool() const
{
return _started && tinyusb_device_mounted;
}
bool ESPUSB::enableDFU(){
#if CFG_TUD_DFU_RT
return tinyusb_enable_interface(USB_INTERFACE_DFU, TUD_DFU_RT_DESC_LEN, load_dfu_descriptor) == ESP_OK;
#endif /* CFG_TUD_DFU_RT */
return false;
}
bool ESPUSB::VID(uint16_t v){
if(!_started){
vid = v;
}
return !_started;
}
uint16_t ESPUSB::VID(void){
return vid;
}
bool ESPUSB::PID(uint16_t p){
if(!_started){
pid = p;
}
return !_started;
}
uint16_t ESPUSB::PID(void){
return pid;
}
bool ESPUSB::firmwareVersion(uint16_t version){
if(!_started){
fw_version = version;
}
return !_started;
}
uint16_t ESPUSB::firmwareVersion(void){
return fw_version;
}
bool ESPUSB::usbVersion(uint16_t version){
if(!_started){
usb_version = version;
}
return !_started;
}
uint16_t ESPUSB::usbVersion(void){
return usb_version;
}
bool ESPUSB::usbPower(uint16_t mA){
if(!_started){
usb_power_ma = mA;
}
return !_started;
}
uint16_t ESPUSB::usbPower(void){
return usb_power_ma;
}
bool ESPUSB::usbClass(uint8_t _class){
if(!_started){
usb_class = _class;
}
return !_started;
}
uint8_t ESPUSB::usbClass(void){
return usb_class;
}
bool ESPUSB::usbSubClass(uint8_t subClass){
if(!_started){
usb_subclass = subClass;
}
return !_started;
}
uint8_t ESPUSB::usbSubClass(void){
return usb_subclass;
}
bool ESPUSB::usbProtocol(uint8_t protocol){
if(!_started){
usb_protocol = protocol;
}
return !_started;
}
uint8_t ESPUSB::usbProtocol(void){
return usb_protocol;
}
bool ESPUSB::usbAttributes(uint8_t attr){
if(!_started){
usb_attributes = attr;
}
return !_started;
}
uint8_t ESPUSB::usbAttributes(void){
return usb_attributes;
}
bool ESPUSB::webUSB(bool enabled){
if(!_started){
webusb_enabled = enabled;
}
return !_started;
}
bool ESPUSB::webUSB(void){
return webusb_enabled;
}
bool ESPUSB::productName(const char * name){
if(!_started){
product_name = name;
}
return !_started;
}
const char * ESPUSB::productName(void){
return product_name.c_str();
}
bool ESPUSB::manufacturerName(const char * name){
if(!_started){
manufacturer_name = name;
}
return !_started;
}
const char * ESPUSB::manufacturerName(void){
return manufacturer_name.c_str();
}
bool ESPUSB::serialNumber(const char * name){
if(!_started){
serial_number = name;
}
return !_started;
}
const char * ESPUSB::serialNumber(void){
return serial_number.c_str();
}
bool ESPUSB::webUSBURL(const char * name){
if(!_started){
webusb_url = name;
}
return !_started;
}
const char * ESPUSB::webUSBURL(void){
return webusb_url.c_str();
}
ESPUSB USB;
#endif /* CONFIG_USB_ENABLED */

View File

@ -1,118 +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_USB_ENABLED
#include "Arduino.h"
#include "USBCDC.h"
#include "esp_event.h"
ESP_EVENT_DECLARE_BASE(ARDUINO_USB_EVENTS);
typedef enum {
ARDUINO_USB_ANY_EVENT = ESP_EVENT_ANY_ID,
ARDUINO_USB_STARTED_EVENT = 0,
ARDUINO_USB_STOPPED_EVENT,
ARDUINO_USB_SUSPEND_EVENT,
ARDUINO_USB_RESUME_EVENT,
ARDUINO_USB_MAX_EVENT,
} arduino_usb_event_t;
typedef union {
struct {
bool remote_wakeup_en;
} suspend;
} arduino_usb_event_data_t;
class ESPUSB {
public:
ESPUSB(size_t event_task_stack_size=2048, uint8_t event_task_priority=5);
~ESPUSB();
void onEvent(esp_event_handler_t callback);
void onEvent(arduino_usb_event_t event, esp_event_handler_t callback);
bool VID(uint16_t v);
uint16_t VID(void);
bool PID(uint16_t p);
uint16_t PID(void);
bool firmwareVersion(uint16_t version);
uint16_t firmwareVersion(void);
bool usbVersion(uint16_t version);
uint16_t usbVersion(void);
bool usbPower(uint16_t mA);
uint16_t usbPower(void);
bool usbClass(uint8_t _class);
uint8_t usbClass(void);
bool usbSubClass(uint8_t subClass);
uint8_t usbSubClass(void);
bool usbProtocol(uint8_t protocol);
uint8_t usbProtocol(void);
bool usbAttributes(uint8_t attr);
uint8_t usbAttributes(void);
bool webUSB(bool enabled);
bool webUSB(void);
bool productName(const char * name);
const char * productName(void);
bool manufacturerName(const char * name);
const char * manufacturerName(void);
bool serialNumber(const char * name);
const char * serialNumber(void);
bool webUSBURL(const char * name);
const char * webUSBURL(void);
bool enableDFU();
bool begin();
operator bool() const;
private:
uint16_t vid;
uint16_t pid;
String product_name;
String manufacturer_name;
String serial_number;
uint16_t fw_version;
uint16_t usb_version;
uint8_t usb_class;
uint8_t usb_subclass;
uint8_t usb_protocol;
uint8_t usb_attributes;
uint16_t usb_power_ma;
bool webusb_enabled;
String webusb_url;
bool _started;
size_t _task_stack_size;
uint8_t _event_task_priority;
};
extern ESPUSB USB;
#endif /* CONFIG_USB_ENABLED */

View File

@ -1,338 +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 "esp32-hal.h"
#include "esp32-hal-tinyusb.h"
#include "USB.h"
#include "USBCDC.h"
#if CONFIG_USB_ENABLED
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);
extern "C" {
#include "tinyusb.h"
}
#if CFG_TUD_CDC
#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");
// Interface number, string index, attributes, detach timeout, transfer size */
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;
}
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);
}
}
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);
}
}
void tud_cdc_rx_cb(uint8_t itf)
{
if(itf < MAX_USB_CDC_DEVICES && devices[itf] != NULL){
devices[itf]->_onRX();
}
}
static size_t tinyusb_cdc_write(uint8_t itf, const uint8_t *buffer, size_t size){
if(itf >= MAX_USB_CDC_DEVICES){
return 0;
}
if(!tud_cdc_n_connected(itf)){
return 0;
}
size_t tosend = size, sofar = 0;
while(tosend){
uint32_t space = tud_cdc_n_write_available(itf);
if(!space){
vTaskDelay(1 / portTICK_PERIOD_MS);
continue;
}
if(tosend < space){
space = tosend;
}
uint32_t sent = tud_cdc_n_write(itf, buffer + sofar, space);
if(!sent){
return sofar;
}
sofar += sent;
tosend -= sent;
tud_cdc_n_write_flush(itf);
}
return sofar;
}
static void ARDUINO_ISR_ATTR cdc0_write_char(char c)
{
tinyusb_cdc_write(0, (const uint8_t *)&c, 1);
}
//void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char);
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) {
tinyusb_enable_interface(USB_INTERFACE_CDC, TUD_CDC_DESC_LEN, load_cdc_descriptor);
if(itf < MAX_USB_CDC_DEVICES){
devices[itf] = this;
arduino_usb_event_handler_register_with(ARDUINO_USB_EVENTS, ARDUINO_USB_STOPPED_EVENT, usb_unplugged_cb, this);
}
}
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){
if(rx_queue){
return 0;
}
rx_queue = xQueueCreate(rx_queue_len, sizeof(uint8_t));
if(!rx_queue){
return 0;
}
return rx_queue_len;
}
void USBCDC::begin(unsigned long baud)
{
setRxBufferSize(256);//default if not preset
}
void USBCDC::end()
{
}
void USBCDC::_onUnplugged(void){
if(connected){
connected = false;
dtr = false;
rts = false;
arduino_usb_cdc_event_data_t p = {0};
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;
dtr = _dtr;
rts = _rts;
if(reboot_enable){
if(!dtr && rts){
if(lineState == CDC_LINE_IDLE){
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 {
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 = {0};
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 && !rts && connected){
connected = false;
arduino_usb_cdc_event_data_t p = {0};
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 = {0};
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){
bit_rate = _bit_rate;
data_bits = _data_bits;
stop_bits = _stop_bits;
parity = _parity;
arduino_usb_cdc_event_data_t p = {0};
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(){
uint8_t buf[CONFIG_USB_CDC_RX_BUFSIZE+1];
uint32_t count = tud_cdc_n_read(itf, buf, CONFIG_USB_CDC_RX_BUFSIZE);
for(uint32_t i=0; i<count; i++){
if(rx_queue == NULL || !xQueueSend(rx_queue, buf+i, 0)){
return;
}
}
arduino_usb_cdc_event_data_t p = {0};
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::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){
return;
}
tud_cdc_n_write_flush(itf);
}
int USBCDC::availableForWrite(void)
{
if(itf >= MAX_USB_CDC_DEVICES){
return -1;
}
return tud_cdc_n_write_available(itf);
}
size_t USBCDC::write(const uint8_t *buffer, size_t size)
{
return tinyusb_cdc_write(itf, buffer, 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_putc1((void (*)(char)) &cdc0_write_char);
} else {
ets_install_putc1(NULL);
}
}
USBCDC::operator bool() const
{
if(itf >= MAX_USB_CDC_DEVICES){
return false;
}
return connected;
}
#if ARDUINO_SERIAL_PORT //Serial used for USB CDC
USBCDC Serial(0);
#endif
#endif /* CONFIG_USB_CDC_ENABLED */
#endif /* CONFIG_USB_ENABLED */

View File

@ -1,132 +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 <inttypes.h>
#include "esp32-hal.h"
#if CONFIG_USB_CDC_ENABLED
#include "esp_event.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_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;
} arduino_usb_cdc_event_data_t;
class USBCDC
{
public:
USBCDC(uint8_t itf=0);
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);
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 _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;
xQueueHandle rx_queue;
};
#if ARDUINO_SERIAL_PORT //Serial used for USB CDC
extern USBCDC Serial;
#endif
#endif /* CONFIG_USB_CDC_ENABLED */

View File

@ -1,46 +0,0 @@
/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
Part of the Wiring project - http://wiring.org.co
Copyright (c) 2004-06 Hernando Barragan
Modified 13 August 2006, David A. Mellis for Arduino - http://www.arduino.cc/
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., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
$Id$
*/
extern "C" {
#include "esp_system.h"
}
//long map(long x, long in_min, long in_max, long out_min, long out_max) {
// const long dividend = out_max - out_min;
// const long divisor = in_max - in_min;
// const long delta = x - in_min;
// return (delta * dividend + (divisor / 2)) / divisor + out_min;
//}
//unsigned int makeWord(unsigned int w)
//{
// return w;
//}
//unsigned int makeWord(unsigned char h, unsigned char l)
//{
// return (h << 8) | l;
//}

View File

@ -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-adc.h"
#include "esp32-hal-log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_attr.h"
#include "soc/rtc_io_reg.h"
#include "soc/rtc_cntl_reg.h"
#include "soc/sens_reg.h"
#include "driver/adc.h"
#include "esp_system.h"
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
#include "esp_adc_cal.h"
#include "esp32/rom/ets_sys.h"
#include "esp_intr_alloc.h"
#define DEFAULT_VREF 1100
static esp_adc_cal_characteristics_t *__analogCharacteristics[2] = {NULL, NULL};
static uint16_t __analogVRef = 0;
static uint8_t __analogVRefPin = 0;
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/rom/ets_sys.h"
#else
#error Target CONFIG_IDF_TARGET is not supported
#endif
#else // ESP32 Before IDF 4.0
#include "rom/ets_sys.h"
#include "esp_intr.h"
#endif
#include "esp32-hal-gpio.h"
static uint8_t __analogAttenuation = 3;//11db
static uint8_t __analogWidth = 3;//12 bits
static uint8_t __analogClockDiv = 1;
void __analogSetClockDiv(uint8_t clockDiv){
if(!clockDiv){
clockDiv = 1;
}
__analogClockDiv = clockDiv;
adc_set_clk_div(__analogClockDiv);
}
void __analogSetAttenuation(adc_attenuation_t attenuation)
{
__analogAttenuation = attenuation & 3;
}
#if CONFIG_IDF_TARGET_ESP32
void __analogSetWidth(uint8_t bits){
if(bits < 9){
bits = 9;
} else if(bits > 12){
bits = 12;
}
__analogWidth = bits - 9;
adc1_config_width(__analogWidth);
}
#endif
void __analogInit(){
static bool initialized = false;
if(initialized){
return;
}
initialized = true;
__analogSetClockDiv(__analogClockDiv);
#if CONFIG_IDF_TARGET_ESP32
__analogSetWidth(__analogWidth + 9);//in bits
#endif
}
void __analogSetPinAttenuation(uint8_t pin, adc_attenuation_t attenuation)
{
int8_t channel = digitalPinToAnalogChannel(pin);
if(channel < 0 || attenuation > 3){
return ;
}
if(channel > 9){
adc2_config_channel_atten(channel - 10, attenuation);
} else {
adc1_config_channel_atten(channel, attenuation);
}
__analogInit();
}
bool __adcAttachPin(uint8_t pin){
int8_t channel = digitalPinToAnalogChannel(pin);
if(channel < 0){
log_e("Pin %u is not ADC pin!", pin);
return false;
}
int8_t pad = digitalPinToTouchChannel(pin);
if(pad >= 0){
#if CONFIG_IDF_TARGET_ESP32
uint32_t touch = READ_PERI_REG(SENS_SAR_TOUCH_ENABLE_REG);
if(touch & (1 << pad)){
touch &= ~((1 << (pad + SENS_TOUCH_PAD_OUTEN2_S))
| (1 << (pad + SENS_TOUCH_PAD_OUTEN1_S))
| (1 << (pad + SENS_TOUCH_PAD_WORKEN_S)));
WRITE_PERI_REG(SENS_SAR_TOUCH_ENABLE_REG, touch);
}
#endif
} else if(pin == 25){
CLEAR_PERI_REG_MASK(RTC_IO_PAD_DAC1_REG, RTC_IO_PDAC1_XPD_DAC | RTC_IO_PDAC1_DAC_XPD_FORCE);//stop dac1
} else if(pin == 26){
CLEAR_PERI_REG_MASK(RTC_IO_PAD_DAC2_REG, RTC_IO_PDAC2_XPD_DAC | RTC_IO_PDAC2_DAC_XPD_FORCE);//stop dac2
}
pinMode(pin, ANALOG);
__analogSetPinAttenuation(pin, __analogAttenuation);
return true;
}
void __analogReadResolution(uint8_t bits)
{
if(!bits || bits > 16){
return;
}
#if CONFIG_IDF_TARGET_ESP32
__analogSetWidth(bits); // hadware from 9 to 12
#endif
}
uint16_t __analogRead(uint8_t pin)
{
int8_t channel = digitalPinToAnalogChannel(pin);
int value = 0;
esp_err_t r = ESP_OK;
if(channel < 0){
log_e("Pin %u is not ADC pin!", pin);
return value;
}
__adcAttachPin(pin);
if(channel > 9){
channel -= 10;
r = adc2_get_raw( channel, __analogWidth, &value);
if ( r == ESP_OK ) {
return value;
} else if ( r == ESP_ERR_INVALID_STATE ) {
log_e("GPIO%u: %s: ADC2 not initialized yet.", pin, esp_err_to_name(r));
} else if ( r == ESP_ERR_TIMEOUT ) {
log_e("GPIO%u: %s: ADC2 is in use by Wi-Fi.", pin, esp_err_to_name(r));
} else {
log_e("GPIO%u: %s", pin, esp_err_to_name(r));
}
} else {
return adc1_get_raw(channel);
}
return value;
}
uint32_t __analogReadMilliVolts(uint8_t pin){
int8_t channel = digitalPinToAnalogChannel(pin);
if(channel < 0){
log_e("Pin %u is not ADC pin!", pin);
return 0;
}
#if CONFIG_IDF_TARGET_ESP32
if(!__analogVRef){
if (esp_adc_cal_check_efuse(ESP_ADC_CAL_VAL_EFUSE_TP) == ESP_OK) {
log_d("eFuse Two Point: Supported");
__analogVRef = DEFAULT_VREF;
}
if (esp_adc_cal_check_efuse(ESP_ADC_CAL_VAL_EFUSE_VREF) == ESP_OK) {
log_d("eFuse Vref: Supported");
__analogVRef = DEFAULT_VREF;
}
if(!__analogVRef){
__analogVRef = DEFAULT_VREF;
if(__analogVRefPin){
esp_adc_cal_characteristics_t chars;
if(adc_vref_to_gpio(ADC_UNIT_2, __analogVRefPin) == ESP_OK){
__analogVRef = __analogRead(__analogVRefPin);
esp_adc_cal_characterize(1, __analogAttenuation, __analogWidth, DEFAULT_VREF, &chars);
__analogVRef = esp_adc_cal_raw_to_voltage(__analogVRef, &chars);
log_d("Vref to GPIO%u: %u", __analogVRefPin, __analogVRef);
}
}
}
}
uint8_t unit = 1;
if(channel > 9){
unit = 2;
}
uint16_t adc_reading = __analogRead(pin);
if(__analogCharacteristics[unit - 1] == NULL){
__analogCharacteristics[unit - 1] = calloc(1, sizeof(esp_adc_cal_characteristics_t));
if(__analogCharacteristics[unit - 1] == NULL){
return 0;
}
esp_adc_cal_value_t val_type = esp_adc_cal_characterize(unit, __analogAttenuation, __analogWidth, __analogVRef, __analogCharacteristics[unit - 1]);
if (val_type == ESP_ADC_CAL_VAL_EFUSE_TP) {
log_i("ADC%u: Characterized using Two Point Value: %u\n", unit, __analogCharacteristics[unit - 1]->vref);
} else if (val_type == ESP_ADC_CAL_VAL_EFUSE_VREF) {
log_i("ADC%u: Characterized using eFuse Vref: %u\n", unit, __analogCharacteristics[unit - 1]->vref);
} else if(__analogVRef != DEFAULT_VREF){
log_i("ADC%u: Characterized using Vref to GPIO%u: %u\n", unit, __analogVRefPin, __analogCharacteristics[unit - 1]->vref);
} else {
log_i("ADC%u: Characterized using Default Vref: %u\n", unit, __analogCharacteristics[unit - 1]->vref);
}
}
return esp_adc_cal_raw_to_voltage(adc_reading, __analogCharacteristics[unit - 1]);
#else
uint16_t adc_reading = __analogRead(pin);
uint16_t max_reading = 8191;
uint16_t max_mv = 1100;
switch(__analogAttenuation){
case 3: max_mv = 3900; break;
case 2: max_mv = 2200; break;
case 1: max_mv = 1500; break;
default: break;
}
return (adc_reading * max_mv) / max_reading;
#endif
}
#if CONFIG_IDF_TARGET_ESP32
void __analogSetVRefPin(uint8_t pin){
if(pin <25 || pin > 27){
pin = 0;
}
__analogVRefPin = pin;
}
int __hallRead() //hall sensor without LNA
{
int Sens_Vp0;
int Sens_Vn0;
int Sens_Vp1;
int Sens_Vn1;
pinMode(36, ANALOG);
pinMode(39, ANALOG);
SET_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL1_REG, SENS_XPD_HALL_FORCE_M); // hall sens force enable
SET_PERI_REG_MASK(RTC_IO_HALL_SENS_REG, RTC_IO_XPD_HALL); // xpd hall
SET_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL1_REG, SENS_HALL_PHASE_FORCE_M); // phase force
CLEAR_PERI_REG_MASK(RTC_IO_HALL_SENS_REG, RTC_IO_HALL_PHASE); // hall phase
Sens_Vp0 = __analogRead(36);
Sens_Vn0 = __analogRead(39);
SET_PERI_REG_MASK(RTC_IO_HALL_SENS_REG, RTC_IO_HALL_PHASE);
Sens_Vp1 = __analogRead(36);
Sens_Vn1 = __analogRead(39);
SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_FORCE_XPD_SAR, 0, SENS_FORCE_XPD_SAR_S);
CLEAR_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL1_REG, SENS_XPD_HALL_FORCE);
CLEAR_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL1_REG, SENS_HALL_PHASE_FORCE);
return (Sens_Vp1 - Sens_Vp0) - (Sens_Vn1 - Sens_Vn0);
}
#endif
extern uint16_t analogRead(uint8_t pin) __attribute__ ((weak, alias("__analogRead")));
extern uint32_t analogReadMilliVolts(uint8_t pin) __attribute__ ((weak, alias("__analogReadMilliVolts")));
extern void analogReadResolution(uint8_t bits) __attribute__ ((weak, alias("__analogReadResolution")));
extern void analogSetClockDiv(uint8_t clockDiv) __attribute__ ((weak, alias("__analogSetClockDiv")));
extern void analogSetAttenuation(adc_attenuation_t attenuation) __attribute__ ((weak, alias("__analogSetAttenuation")));
extern void analogSetPinAttenuation(uint8_t pin, adc_attenuation_t attenuation) __attribute__ ((weak, alias("__analogSetPinAttenuation")));
extern bool adcAttachPin(uint8_t pin) __attribute__ ((weak, alias("__adcAttachPin")));
#if CONFIG_IDF_TARGET_ESP32
extern void analogSetVRefPin(uint8_t pin) __attribute__ ((weak, alias("__analogSetVRefPin")));
extern void analogSetWidth(uint8_t bits) __attribute__ ((weak, alias("__analogSetWidth")));
extern int hallRead() __attribute__ ((weak, alias("__hallRead")));
#endif

View File

@ -1,105 +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_ADC_H_
#define MAIN_ESP32_HAL_ADC_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stdbool.h>
//#include "esp32-hal.h"
typedef enum {
ADC_0db,
ADC_2_5db,
ADC_6db,
ADC_11db
} 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 divider for the ADC clock.
* Default is 1
* Range is 1 - 255
* */
void analogSetClockDiv(uint8_t clockDiv);
/*
* 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);
/*
* Attach pin to ADC (will also clear any other analog mode that could be on)
* */
bool adcAttachPin(uint8_t pin);
#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);
/*
* Set pin to use for ADC calibration if the esp is not already calibrated (25, 26 or 27)
* */
void analogSetVRefPin(uint8_t pin);
/*
* Get value for HALL sensor (without LNA)
* connected to pins 36(SVP) and 39(SVN)
* */
int hallRead();
#endif
#ifdef __cplusplus
}
#endif
#endif /* MAIN_ESP32_HAL_ADC_H_ */

View File

@ -159,20 +159,20 @@ bool setCpuFrequencyMhz(uint32_t cpu_freq_mhz){
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);
log_e("Bad frequency: %lu 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);
log_e("Bad frequency: %lu MHz! Options are: 240, 160, 80, %u, %u and %u MHz", cpu_freq_mhz, xtal, xtal/2, xtal/4);
return false;
}
}
#endif
if(cpu_freq_mhz > xtal && cpu_freq_mhz != 240 && cpu_freq_mhz != 160 && cpu_freq_mhz != 80){
if(xtal >= RTC_XTAL_FREQ_40M){
log_e("Bad frequency: %u MHz! Options are: 240, 160, 80, %u, %u and %u MHz", cpu_freq_mhz, xtal, xtal/2, xtal/4);
log_e("Bad frequency: %lu MHz! Options are: 240, 160, 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, 80, %u and %u MHz", cpu_freq_mhz, xtal, xtal/2);
log_e("Bad frequency: %lu MHz! Options are: 240, 160, 80, %u and %u MHz", cpu_freq_mhz, xtal, xtal/2);
}
return false;
}
@ -195,7 +195,7 @@ bool setCpuFrequencyMhz(uint32_t cpu_freq_mhz){
}
//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);
log_e("CPU clock could not be set to %lu MHz", cpu_freq_mhz);
return false;
}
//Current APB

View File

@ -1,57 +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.h"
#include "esp_attr.h"
#include "soc/rtc_io_reg.h"
#include "soc/rtc_cntl_reg.h"
#include "soc/rtc_io_periph.h"
#include "soc/sens_reg.h"
#include "soc/sens_struct.h"
#include "driver/dac.h"
#include "esp32-hal-gpio.h"
#if CONFIG_IDF_TARGET_ESP32
#define DAC1 25
#define DAC2 26
#elif CONFIG_IDF_TARGET_ESP32S2
#define DAC1 17
#define DAC2 18
#else
#error Target CONFIG_IDF_TARGET is not supported
#endif
void ARDUINO_ISR_ATTR __dacWrite(uint8_t pin, uint8_t value)
{
if(pin < DAC1 || pin > DAC2){
return;//not dac pin
}
pinMode(pin, ANALOG);
uint8_t channel = pin - DAC1;
#if CONFIG_IDF_TARGET_ESP32
CLEAR_PERI_REG_MASK(SENS_SAR_DAC_CTRL1_REG, SENS_SW_TONE_EN);
#elif CONFIG_IDF_TARGET_ESP32S2
SENS.sar_dac_ctrl1.dac_clkgate_en = 1;
#endif
RTCIO.pad_dac[channel].dac_xpd_force = 1;
RTCIO.pad_dac[channel].xpd_dac = 1;
if (channel == 0) {
SENS.sar_dac_ctrl2.dac_cw_en1 = 0;
} else if (channel == 1) {
SENS.sar_dac_ctrl2.dac_cw_en2 = 0;
}
RTCIO.pad_dac[channel].dac = value;
}
extern void dacWrite(uint8_t pin, uint8_t value) __attribute__ ((weak, alias("__dacWrite")));

View File

@ -1,33 +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_DAC_H_
#define MAIN_ESP32_HAL_DAC_H_
#ifdef __cplusplus
extern "C" {
#endif
void dacWrite(uint8_t pin, uint8_t value);
#ifdef __cplusplus
}
#endif
#endif /* MAIN_ESP32_HAL_DAC_H_ */

View File

@ -1,392 +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.h"
#include "esp32-hal-gpio.h"
#include "pins_arduino.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_attr.h"
#include "soc/gpio_reg.h"
#include "soc/io_mux_reg.h"
#include "soc/gpio_struct.h"
#include "soc/rtc_io_reg.h"
#include "soc/rtc_io_periph.h"
#include "esp_system.h"
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
#include "esp32/rom/ets_sys.h"
#include "esp32/rom/gpio.h"
#include "esp_intr_alloc.h"
#define GPIO_FUNC 2
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/rom/ets_sys.h"
#include "esp32s2/rom/gpio.h"
#include "esp_intr_alloc.h"
#include "soc/periph_defs.h"
#define GPIO_FUNC 1
#else
#error Target CONFIG_IDF_TARGET is not supported
#endif
#else // ESP32 Before IDF 4.0
#include "rom/ets_sys.h"
#include "rom/gpio.h"
#include "esp_intr.h"
#endif
#if CONFIG_IDF_TARGET_ESP32
const int8_t esp32_adc2gpio[20] = {36, 37, 38, 39, 32, 33, 34, 35, -1, -1, 4, 0, 2, 15, 13, 12, 14, 27, 25, 26};
#elif CONFIG_IDF_TARGET_ESP32S2
const int8_t esp32_adc2gpio[20] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20};
#endif
const DRAM_ATTR esp32_gpioMux_t esp32_gpioMux[SOC_GPIO_PIN_COUNT]={
#if CONFIG_IDF_TARGET_ESP32
{0x44, 11, 11, 1},
{0x88, -1, -1, -1},
{0x40, 12, 12, 2},
{0x84, -1, -1, -1},
{0x48, 10, 10, 0},
{0x6c, -1, -1, -1},
{0x60, -1, -1, -1},
{0x64, -1, -1, -1},
{0x68, -1, -1, -1},
{0x54, -1, -1, -1},
{0x58, -1, -1, -1},
{0x5c, -1, -1, -1},
{0x34, 15, 15, 5},
{0x38, 14, 14, 4},
{0x30, 16, 16, 6},
{0x3c, 13, 13, 3},
{0x4c, -1, -1, -1},
{0x50, -1, -1, -1},
{0x70, -1, -1, -1},
{0x74, -1, -1, -1},
{0x78, -1, -1, -1},
{0x7c, -1, -1, -1},
{0x80, -1, -1, -1},
{0x8c, -1, -1, -1},
{0, -1, -1, -1},
{0x24, 6, 18, -1}, //DAC1
{0x28, 7, 19, -1}, //DAC2
{0x2c, 17, 17, 7},
{0, -1, -1, -1},
{0, -1, -1, -1},
{0, -1, -1, -1},
{0, -1, -1, -1},
{0x1c, 9, 4, 8},
{0x20, 8, 5, 9},
{0x14, 4, 6, -1},
{0x18, 5, 7, -1},
{0x04, 0, 0, -1},
{0x08, 1, 1, -1},
{0x0c, 2, 2, -1},
{0x10, 3, 3, -1}
#elif CONFIG_IDF_TARGET_ESP32S2
{0x04, 0, -1, -1},
{0x08, 1, 0, 1},
{0x0c, 2, 1, 2},
{0x10, 3, 2, 3},
{0x14, 4, 3, 4},
{0x18, 5, 4, 5},
{0x1c, 6, 5, 6},
{0x20, 7, 6, 7},
{0x24, 8, 7, 8},
{0x28, 9, 8, 9},//FSPI_HD
{0x2c, 10, 9, 10},//FSPI_CS0 / FSPI_D4
{0x30, 11, 10, 11},//FSPI_D / FSPI_D5
{0x34, 12, 11, 12},//FSPI_CLK / FSPI_D6
{0x38, 13, 12, 13},//FSPI_Q / FSPI_D7
{0x3c, 14, 13, 14},//FSPI_WP / FSPI_DQS
{0x40, 15, 14, -1},//32K+ / RTS0
{0x44, 16, 15, -1},//32K- / CTS0
{0x48, 17, 16, -1},//DAC1 / TXD1
{0x4c, 18, 17, -1},//DAC2 / RXD1
{0x50, 19, 18, -1},//USB D- / RTS1
{0x54, 20, 19, -1},//USB D+ / CTS1
{0x58, 21, -1, -1},//SDA?
{ 0, -1, -1, -1},//UNAVAILABLE
{ 0, -1, -1, -1},//UNAVAILABLE
{ 0, -1, -1, -1},//UNAVAILABLE
{ 0, -1, -1, -1},//UNAVAILABLE
{0x6c, -1, -1, -1},//RESERVED SPI_CS1
{0x70, -1, -1, -1},//RESERVED SPI_HD
{0x74, -1, -1, -1},//RESERVED SPI_WP
{0x78, -1, -1, -1},//RESERVED SPI_CS0
{0x7c, -1, -1, -1},//RESERVED SPI_CLK
{0x80, -1, -1, -1},//RESERVED SPI_Q
{0x84, -1, -1, -1},//RESERVED SPI_D
{0x88, -1, -1, -1},//FSPI_HD
{0x8c, -1, -1, -1},//FSPI_CS0
{0x90, -1, -1, -1},//FSPI_D
{0x94, -1, -1, -1},//FSPI_CLK
{0x98, -1, -1, -1},//FSPI_Q
{0x9c, -1, -1, -1},//FSPI_WP
{0xa0, -1, -1, -1},//MTCK
{0xa4, -1, -1, -1},//MTDO
{0xa8, -1, -1, -1},//MTDI
{0xac, -1, -1, -1},//MTMS
{0xb0, -1, -1, -1},//TXD0
{0xb4, -1, -1, -1},//RXD0
{0xb8, -1, -1, -1},//SCL?
{0xbc, -1, -1, -1},//INPUT ONLY
{0, -1, -1, -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"
extern void ARDUINO_ISR_ATTR __pinMode(uint8_t pin, uint8_t mode)
{
if(!digitalPinIsValid(pin)) {
return;
}
int8_t rtc_io = esp32_gpioMux[pin].rtc;
uint32_t rtc_reg = (rtc_io != -1)?rtc_io_desc[rtc_io].reg:0;
if(mode == ANALOG) {
if(!rtc_reg) {
return;//not rtc pin
}
#if CONFIG_IDF_TARGET_ESP32S2
SENS.sar_io_mux_conf.iomux_clk_gate_en = 1;
#endif
SET_PERI_REG_MASK(rtc_io_desc[rtc_io].reg, (rtc_io_desc[rtc_io].mux));
SET_PERI_REG_BITS(rtc_io_desc[rtc_io].reg, RTC_IO_TOUCH_PAD1_FUN_SEL_V, 0, rtc_io_desc[rtc_io].func);
RTCIO.pin[rtc_io].pad_driver = 0;//OD = 1
RTCIO.enable_w1tc.w1tc = (1U << rtc_io);
CLEAR_PERI_REG_MASK(rtc_io_desc[rtc_io].reg, rtc_io_desc[rtc_io].ie);
if (rtc_io_desc[rtc_io].pullup) {
CLEAR_PERI_REG_MASK(rtc_io_desc[rtc_io].reg, rtc_io_desc[rtc_io].pullup);
}
if (rtc_io_desc[rtc_io].pulldown) {
CLEAR_PERI_REG_MASK(rtc_io_desc[rtc_io].reg, rtc_io_desc[rtc_io].pulldown);
}
ESP_REG(DR_REG_IO_MUX_BASE + esp32_gpioMux[pin].reg) = ((uint32_t)GPIO_FUNC << MCU_SEL_S) | ((uint32_t)2 << FUN_DRV_S) | FUN_IE;
return;
}
//RTC pins PULL settings
if(rtc_reg) {
ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_io_desc[rtc_io].mux);
if(mode & PULLUP) {
ESP_REG(rtc_reg) = (ESP_REG(rtc_reg) | rtc_io_desc[rtc_io].pullup) & ~(rtc_io_desc[rtc_io].pulldown);
} else if(mode & PULLDOWN) {
ESP_REG(rtc_reg) = (ESP_REG(rtc_reg) | rtc_io_desc[rtc_io].pulldown) & ~(rtc_io_desc[rtc_io].pullup);
} else {
ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_io_desc[rtc_io].pullup | rtc_io_desc[rtc_io].pulldown);
}
}
uint32_t pinFunction = 0, pinControl = 0;
if(mode & INPUT) {
if(pin < 32) {
GPIO.enable_w1tc = ((uint32_t)1 << pin);
} else {
GPIO.enable1_w1tc.val = ((uint32_t)1 << (pin - 32));
}
} else if(mode & OUTPUT) {
if(pin >= NUM_OUPUT_PINS){
return;
} else if(pin < 32) {
GPIO.enable_w1ts = ((uint32_t)1 << pin);
} else {
GPIO.enable1_w1ts.val = ((uint32_t)1 << (pin - 32));
}
}
if(mode & PULLUP) {
pinFunction |= FUN_PU;
} else if(mode & PULLDOWN) {
pinFunction |= FUN_PD;
}
pinFunction |= ((uint32_t)2 << FUN_DRV_S);//what are the drivers?
pinFunction |= FUN_IE;//input enable but required for output as well?
if(mode & (INPUT | OUTPUT)) {
#if CONFIG_IDF_TARGET_ESP32
pinFunction |= ((uint32_t)2 << MCU_SEL_S);
#elif CONFIG_IDF_TARGET_ESP32S2
pinFunction |= ((uint32_t)1 << MCU_SEL_S);
#endif
} else if(mode == SPECIAL) {
#if CONFIG_IDF_TARGET_ESP32
pinFunction |= ((uint32_t)(((pin)==RX||(pin)==TX)?0:1) << MCU_SEL_S);
#elif CONFIG_IDF_TARGET_ESP32S2
pinFunction |= ((uint32_t)(((pin)==RX||(pin)==TX)?0:2) << MCU_SEL_S);
#endif
} else {
pinFunction |= ((uint32_t)(mode >> 5) << MCU_SEL_S);
}
ESP_REG(DR_REG_IO_MUX_BASE + esp32_gpioMux[pin].reg) = pinFunction;
if(mode & OPEN_DRAIN) {
pinControl = (1 << GPIO_PIN0_PAD_DRIVER_S);
}
GPIO.pin[pin].val = pinControl;
}
extern void ARDUINO_ISR_ATTR __digitalWrite(uint8_t pin, uint8_t val)
{
if(val) {
if(pin < 32) {
GPIO.out_w1ts = ((uint32_t)1 << pin);
} else if(pin < NUM_OUPUT_PINS) {
GPIO.out1_w1ts.val = ((uint32_t)1 << (pin - 32));
}
} else {
if(pin < 32) {
GPIO.out_w1tc = ((uint32_t)1 << pin);
} else if(pin < NUM_OUPUT_PINS) {
GPIO.out1_w1tc.val = ((uint32_t)1 << (pin - 32));
}
}
}
extern int ARDUINO_ISR_ATTR __digitalRead(uint8_t pin)
{
if(pin < 32) {
return (GPIO.in >> pin) & 0x1;
} else if(pin < GPIO_PIN_COUNT) {
return (GPIO.in1.val >> (pin - 32)) & 0x1;
}
return 0;
}
static intr_handle_t gpio_intr_handle = NULL;
static void ARDUINO_ISR_ATTR __onPinInterrupt()
{
uint32_t gpio_intr_status_l=0;
uint32_t gpio_intr_status_h=0;
gpio_intr_status_l = GPIO.status;
gpio_intr_status_h = GPIO.status1.val;
GPIO.status_w1tc = gpio_intr_status_l;//Clear intr for gpio0-gpio31
GPIO.status1_w1tc.val = gpio_intr_status_h;//Clear intr for gpio32-39
uint8_t pin=0;
if(gpio_intr_status_l) {
do {
if(gpio_intr_status_l & ((uint32_t)1 << pin)) {
if(__pinInterruptHandlers[pin].fn) {
if(__pinInterruptHandlers[pin].arg){
((voidFuncPtrArg)__pinInterruptHandlers[pin].fn)(__pinInterruptHandlers[pin].arg);
} else {
__pinInterruptHandlers[pin].fn();
}
}
}
} while(++pin<32);
}
if(gpio_intr_status_h) {
pin=32;
do {
if(gpio_intr_status_h & ((uint32_t)1 << (pin - 32))) {
if(__pinInterruptHandlers[pin].fn) {
if(__pinInterruptHandlers[pin].arg){
((voidFuncPtrArg)__pinInterruptHandlers[pin].fn)(__pinInterruptHandlers[pin].arg);
} else {
__pinInterruptHandlers[pin].fn();
}
}
}
} while(++pin<GPIO_PIN_COUNT);
}
}
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;
if(!interrupt_initialized) {
interrupt_initialized = true;
esp_intr_alloc(ETS_GPIO_INTR_SOURCE, (int)ARDUINO_ISR_FLAG, __onPinInterrupt, NULL, &gpio_intr_handle);
}
// 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;
esp_intr_disable(gpio_intr_handle);
#if CONFIG_IDF_TARGET_ESP32
if(esp_intr_get_cpu(gpio_intr_handle)) { //APP_CPU
#endif
GPIO.pin[pin].int_ena = 1;
#if CONFIG_IDF_TARGET_ESP32
} else { //PRO_CPU
GPIO.pin[pin].int_ena = 4;
}
#endif
GPIO.pin[pin].int_type = intr_type;
esp_intr_enable(gpio_intr_handle);
}
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)
{
esp_intr_disable(gpio_intr_handle);
if (__pinInterruptHandlers[pin].functional && __pinInterruptHandlers[pin].arg)
{
cleanupFunctional(__pinInterruptHandlers[pin].arg);
}
__pinInterruptHandlers[pin].fn = NULL;
__pinInterruptHandlers[pin].arg = NULL;
__pinInterruptHandlers[pin].functional = false;
GPIO.pin[pin].int_ena = 0;
GPIO.pin[pin].int_type = 0;
esp_intr_enable(gpio_intr_handle);
}
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")));

View File

@ -1,100 +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 "stdint.h"
#include "soc/soc_caps.h"
#if (CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
#define NUM_OUPUT_PINS 45
#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
#define OUTPUT 0x02
#define PULLUP 0x04
#define INPUT_PULLUP 0x05
#define PULLDOWN 0x08
#define INPUT_PULLDOWN 0x09
#define OPEN_DRAIN 0x10
#define OUTPUT_OPEN_DRAIN 0x12
#define SPECIAL 0xF0
#define FUNCTION_1 0x00
#define FUNCTION_2 0x20
#define FUNCTION_3 0x40
#define FUNCTION_4 0x60
#define FUNCTION_5 0x80
#define FUNCTION_6 0xA0
#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
typedef struct {
uint8_t reg; /*!< GPIO register offset from DR_REG_IO_MUX_BASE */
int8_t rtc; /*!< RTC GPIO number (-1 if not RTC GPIO pin) */
int8_t adc; /*!< ADC Channel number (-1 if not ADC pin) */
int8_t touch; /*!< Touch Channel number (-1 if not Touch pin) */
} esp32_gpioMux_t;
extern const esp32_gpioMux_t esp32_gpioMux[SOC_GPIO_PIN_COUNT];
extern const int8_t esp32_adc2gpio[20];
#define digitalPinIsValid(pin) ((pin) < SOC_GPIO_PIN_COUNT && esp32_gpioMux[(pin)].reg)
#define digitalPinCanOutput(pin) ((pin) < NUM_OUPUT_PINS && esp32_gpioMux[(pin)].reg)
#define digitalPinToRtcPin(pin) (((pin) < SOC_GPIO_PIN_COUNT)?esp32_gpioMux[(pin)].rtc:-1)
#define digitalPinToAnalogChannel(pin) (((pin) < SOC_GPIO_PIN_COUNT)?esp32_gpioMux[(pin)].adc:-1)
#define digitalPinToTouchChannel(pin) (((pin) < SOC_GPIO_PIN_COUNT)?esp32_gpioMux[(pin)].touch:-1)
#define digitalPinToDacChannel(pin) (((pin) == PIN_DAC1)?0:((pin) == PIN_DAC2)?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);
#ifdef __cplusplus
}
#endif
#endif /* MAIN_ESP32_HAL_GPIO_H_ */

View File

@ -27,7 +27,6 @@
#include "esp_attr.h"
#include "esp32-hal-cpu.h" // cpu clock change support 31DEC2018
#include "esp32-hal-log.h"
#include "esp32-hal-gpio.h"
#include "esp32-hal-matrix.h"
#include "esp32-hal-misc.h"
@ -44,6 +43,8 @@
#include "rom/ets_sys.h"
#endif
#include "driver/gpio.h"
#include <esp_log.h>
#define TAG "ARDUINO"
#if CONFIG_IDF_TARGET_ESP32
@ -338,7 +339,7 @@ static void i2cDumpDqData(i2c_t * i2c)
static void i2cDumpI2c(i2c_t * i2c)
{
log_e("i2c=%p",i2c);
log_i("dev=%p date=%u",i2c->dev,i2c->dev->date);
log_i("dev=%p date=%"PRIu32,i2c->dev,i2c->dev->date);
#if !CONFIG_DISABLE_HAL_LOCKS
log_i("lock=%p",i2c->lock);
#endif
@ -346,14 +347,14 @@ static void i2cDumpI2c(i2c_t * i2c)
log_i("mode=%d",i2c->mode);
log_i("stage=%d",i2c->stage);
log_i("error=%d",i2c->error);
log_i("event=%p bits=%x",i2c->i2c_event,(i2c->i2c_event)?xEventGroupGetBits(i2c->i2c_event):0);
log_i("event=%p bits=%lx",i2c->i2c_event,(i2c->i2c_event)?xEventGroupGetBits(i2c->i2c_event):0);
log_i("intr_handle=%p",i2c->intr_handle);
log_i("dq=%p",i2c->dq);
log_i("queueCount=%d",i2c->queueCount);
log_i("queuePos=%d",i2c->queuePos);
log_i("errorByteCnt=%d",i2c->errorByteCnt);
log_i("errorQueue=%d",i2c->errorQueue);
log_i("debugFlags=0x%08X",i2c->debugFlags);
log_i("debugFlags=0x%08" PRIu32 "X",i2c->debugFlags);
if(i2c->dq) {
i2cDumpDqData(i2c);
}
@ -479,7 +480,7 @@ static void i2cApbChangeCallback(void * arg, apb_change_ev_t ev_type, uint32_t o
switch(ev_type){
case APB_BEFORE_CHANGE :
if(new_apb < 3000000) {// too slow
log_e("apb speed %d too slow",new_apb);
log_e("apb speed %lu too slow",new_apb);
break;
}
I2C_MUTEX_LOCK(); // lock will spin until current transaction is completed
@ -779,7 +780,7 @@ static void ARDUINO_ISR_ATTR emptyRxFifo(i2c_t * i2c)
}
if(i2c->queuePos >= i2c->queueCount){ // bad stuff, rx data but no place to put it!
log_e("no Storage location for %d",moveCnt);
log_e("no Storage location for %lu",moveCnt);
// discard
while(moveCnt>0){
d = i2c->dev->fifo_data.val;
@ -795,7 +796,7 @@ static void ARDUINO_ISR_ATTR emptyRxFifo(i2c_t * i2c)
moveCnt = (tdq->length - tdq->position);
}
} else {// error
log_e("RxEmpty(%d) call on TxBuffer? dq=%d",moveCnt,i2c->queuePos);
log_e("RxEmpty(%4lu) call on TxBuffer? dq=%d",moveCnt,i2c->queuePos);
// discard
while(moveCnt>0){
d = i2c->dev->fifo_data.val;
@ -1032,7 +1033,7 @@ static void ARDUINO_ISR_ATTR i2c_isr_handler_default(void* arg)
if(activeInt) { // clear unhandled if possible? What about Disabling interrupt?
p_i2c->dev->int_clr.val = activeInt;
log_e("unknown int=%x",activeInt);
log_e("unknown int=%lx",activeInt);
// disable unhandled IRQ,
p_i2c->dev->int_ena.val = p_i2c->dev->int_ena.val & (~activeInt);
}
@ -1280,7 +1281,7 @@ i2c_err_t i2cProcQueue(i2c_t * i2c, uint32_t *readCount, uint16_t timeOutMillis)
}
if(ret!=ESP_OK) {
log_e("install interrupt handler Failed=%d",ret);
log_e("install interrupt handler Failed=%lu",ret);
I2C_MUTEX_UNLOCK();
return I2C_ERROR_MEMORY;
}
@ -1432,28 +1433,52 @@ static bool i2cCheckLineState(int8_t sda, int8_t scl){
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
digitalWrite(sda, HIGH);
digitalWrite(scl, HIGH);
pinMode(sda, PULLUP|OPEN_DRAIN|INPUT);
pinMode(scl, PULLUP|OPEN_DRAIN|OUTPUT);
gpio_set_level(sda, 1);
gpio_set_level(scl, 1);
{
const gpio_config_t config = {
.pin_bit_mask = 1ULL << sda,
.mode = GPIO_MODE_INPUT_OUTPUT_OD,
.pull_up_en = GPIO_PULLUP_ENABLE,
.pull_down_en = GPIO_PULLDOWN_DISABLE,
.intr_type = GPIO_INTR_DISABLE,
};
if(!digitalRead(sda) || !digitalRead(scl)) { // bus in busy state
log_w("invalid state sda(%d)=%d, scl(%d)=%d", sda, digitalRead(sda), scl, digitalRead(scl));
digitalWrite(scl, HIGH);
const int result = gpio_config(&config);
if (result != ESP_OK)
ESP_LOGE(TAG, "gpio_config() failed %s", esp_err_to_name(result));
}
{
const gpio_config_t config = {
.pin_bit_mask = 1ULL << scl,
.mode = GPIO_MODE_OUTPUT_OD,
.pull_up_en = GPIO_PULLUP_ENABLE,
.pull_down_en = GPIO_PULLDOWN_DISABLE,
.intr_type = GPIO_INTR_DISABLE,
};
const int result = gpio_config(&config);
if (result != ESP_OK)
ESP_LOGE(TAG, "gpio_config() failed %s", esp_err_to_name(result));
}
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));
gpio_set_level(scl, 1);
for(uint8_t a=0; a<9; a++) {
delayMicroseconds(5);
digitalWrite(scl, LOW);
gpio_set_level(scl, 0);
delayMicroseconds(5);
digitalWrite(scl, HIGH);
if(digitalRead(sda)){ // bus recovered
gpio_set_level(scl, 1);
if(gpio_get_level(sda)){ // bus recovered
log_d("Recovered after %d Cycles",a+1);
break;
}
}
}
if(!digitalRead(sda) || !digitalRead(scl)) { // bus in busy state
log_e("Bus Invalid State, TwoWire() Can't init sda=%d, scl=%d",digitalRead(sda),digitalRead(scl));
if(!gpio_get_level(sda) || !gpio_get_level(scl)) { // bus in busy state
log_e("Bus Invalid State, TwoWire() Can't init sda=%d, scl=%d",gpio_get_level(sda),gpio_get_level(scl));
return false; // bus is busy
}
return true;
@ -1464,8 +1489,20 @@ i2c_err_t i2cAttachSCL(i2c_t * i2c, int8_t scl)
if(i2c == NULL) {
return I2C_ERROR_DEV;
}
digitalWrite(scl, HIGH);
pinMode(scl, OPEN_DRAIN | PULLUP | INPUT | OUTPUT);
gpio_set_level(scl, 1);
{
const gpio_config_t config = {
.pin_bit_mask = (1ULL << scl),
.mode = GPIO_MODE_INPUT_OUTPUT_OD,
.pull_up_en = GPIO_PULLUP_ENABLE,
.pull_down_en = GPIO_PULLDOWN_DISABLE,
.intr_type = GPIO_INTR_DISABLE
};
const int result = gpio_config(&config);
if (result != ESP_OK)
ESP_LOGE(TAG, "gpio_config() failed %s", esp_err_to_name(result));
}
pinMatrixOutAttach(scl, I2C_SCL_IDX(i2c->num), false, false);
pinMatrixInAttach(scl, I2C_SCL_IDX(i2c->num), false);
return I2C_ERROR_OK;
@ -1478,7 +1515,19 @@ i2c_err_t i2cDetachSCL(i2c_t * i2c, int8_t scl)
}
pinMatrixOutDetach(scl, false, false);
pinMatrixInDetach(I2C_SCL_IDX(i2c->num), false, false);
pinMode(scl, INPUT | PULLUP);
{
const gpio_config_t config = {
.pin_bit_mask = (1ULL << scl),
.mode = GPIO_MODE_INPUT,
.pull_up_en = GPIO_PULLUP_ENABLE,
.pull_down_en = GPIO_PULLDOWN_DISABLE,
.intr_type = GPIO_INTR_DISABLE
};
const int result = gpio_config(&config);
if (result != ESP_OK)
ESP_LOGE(TAG, "gpio_config() failed %s", esp_err_to_name(result));
}
return I2C_ERROR_OK;
}
@ -1487,8 +1536,20 @@ i2c_err_t i2cAttachSDA(i2c_t * i2c, int8_t sda)
if(i2c == NULL) {
return I2C_ERROR_DEV;
}
digitalWrite(sda, HIGH);
pinMode(sda, OPEN_DRAIN | PULLUP | INPUT | OUTPUT );
gpio_set_level(sda, 1);
{
const gpio_config_t config = {
.pin_bit_mask = (1ULL << sda),
.mode = GPIO_MODE_INPUT_OUTPUT_OD,
.pull_up_en = GPIO_PULLUP_ENABLE,
.pull_down_en = GPIO_PULLDOWN_DISABLE,
.intr_type = GPIO_INTR_DISABLE
};
const int result = gpio_config(&config);
if (result != ESP_OK)
ESP_LOGE(TAG, "gpio_config() failed %s", esp_err_to_name(result));
}
pinMatrixOutAttach(sda, I2C_SDA_IDX(i2c->num), false, false);
pinMatrixInAttach(sda, I2C_SDA_IDX(i2c->num), false);
return I2C_ERROR_OK;
@ -1501,7 +1562,19 @@ i2c_err_t i2cDetachSDA(i2c_t * i2c, int8_t sda)
}
pinMatrixOutDetach(sda, false, false);
pinMatrixInDetach(I2C_SDA_IDX(i2c->num), false, false);
pinMode(sda, INPUT | PULLUP);
{
const gpio_config_t config = {
.pin_bit_mask = (1ULL << sda),
.mode = GPIO_MODE_INPUT,
.pull_up_en = GPIO_PULLUP_ENABLE,
.pull_down_en = GPIO_PULLDOWN_DISABLE,
.intr_type = GPIO_INTR_DISABLE
};
const int result = gpio_config(&config);
if (result != ESP_OK)
ESP_LOGE(TAG, "gpio_config() failed %s", esp_err_to_name(result));
}
return I2C_ERROR_OK;
}

View File

@ -1,319 +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.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "esp32-hal-matrix.h"
#include "esp32-hal-log.h"
#include "soc/dport_reg.h"
#include "soc/ledc_reg.h"
#include "soc/ledc_struct.h"
#include "esp32-hal-cpu.h"
#include "esp32-hal-gpio.h"
#include "esp32-hal-ledc.h"
#include "esp_system.h"
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
#include "esp32/rom/ets_sys.h"
#define LAST_CHAN (15)
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/rom/ets_sys.h"
#define LAST_CHAN (7)
#define LEDC_DIV_NUM_HSTIMER0_V LEDC_CLK_DIV_LSTIMER0_V
#else
#error Target CONFIG_IDF_TARGET is not supported
#endif
#else // ESP32 Before IDF 4.0
#include "rom/ets_sys.h"
#endif
#if CONFIG_DISABLE_HAL_LOCKS
#define LEDC_MUTEX_LOCK()
#define LEDC_MUTEX_UNLOCK()
#else
#define LEDC_MUTEX_LOCK() do {} while (xSemaphoreTake(_ledc_sys_lock, portMAX_DELAY) != pdPASS)
#define LEDC_MUTEX_UNLOCK() xSemaphoreGive(_ledc_sys_lock)
SemaphoreHandle_t _ledc_sys_lock = NULL;
#endif
/*
* LEDC Chan to Group/Channel/Timer Mapping
** ledc: 0 => Group: 0, Channel: 0, Timer: 0
** ledc: 1 => Group: 0, Channel: 1, Timer: 0
** ledc: 2 => Group: 0, Channel: 2, Timer: 1
** ledc: 3 => Group: 0, Channel: 3, Timer: 1
** ledc: 4 => Group: 0, Channel: 4, Timer: 2
** ledc: 5 => Group: 0, Channel: 5, Timer: 2
** ledc: 6 => Group: 0, Channel: 6, Timer: 3
** ledc: 7 => Group: 0, Channel: 7, Timer: 3
** ledc: 8 => Group: 1, Channel: 0, Timer: 0
** ledc: 9 => Group: 1, Channel: 1, Timer: 0
** ledc: 10 => Group: 1, Channel: 2, Timer: 1
** ledc: 11 => Group: 1, Channel: 3, Timer: 1
** ledc: 12 => Group: 1, Channel: 4, Timer: 2
** ledc: 13 => Group: 1, Channel: 5, Timer: 2
** ledc: 14 => Group: 1, Channel: 6, Timer: 3
** ledc: 15 => Group: 1, Channel: 7, Timer: 3
*/
#define LEDC_CHAN(g,c) LEDC.channel_group[(g)].channel[(c)]
#define LEDC_TIMER(g,t) LEDC.timer_group[(g)].timer[(t)]
static void _on_apb_change(void * arg, apb_change_ev_t ev_type, uint32_t old_apb, uint32_t new_apb){
if(ev_type == APB_AFTER_CHANGE && old_apb != new_apb){
uint16_t iarg = *(uint16_t*)arg;
uint8_t chan = 0;
old_apb /= 1000000;
new_apb /= 1000000;
while(iarg){ // run though all active channels, adjusting timing configurations
if(iarg & 1) {// this channel is active
uint8_t group=(chan/8), timer=((chan/2)%4);
if(LEDC_TIMER(group, timer).conf.tick_sel){
LEDC_MUTEX_LOCK();
uint32_t old_div = LEDC_TIMER(group, timer).conf.clock_divider;
uint32_t div_num = (new_apb * old_div) / old_apb;
if(div_num > LEDC_DIV_NUM_HSTIMER0_V){
div_num = ((REF_CLK_FREQ /1000000) * old_div) / old_apb;
if(div_num > LEDC_DIV_NUM_HSTIMER0_V) {
div_num = LEDC_DIV_NUM_HSTIMER0_V;//lowest clock possible
}
LEDC_TIMER(group, timer).conf.tick_sel = 0;
} else if(div_num < 256) {
div_num = 256;//highest clock possible
}
LEDC_TIMER(group, timer).conf.clock_divider = div_num;
LEDC_MUTEX_UNLOCK();
}
else {
log_d("using REF_CLK chan=%d",chan);
}
}
iarg = iarg >> 1;
chan++;
}
}
}
//uint32_t frequency = (80MHz or 1MHz)/((div_num / 256.0)*(1 << bit_num));
static void _ledcSetupTimer(uint8_t chan, uint32_t div_num, uint8_t bit_num, bool apb_clk)
{
uint8_t group=(chan/8), timer=((chan/2)%4);
static bool tHasStarted = false;
static uint16_t _activeChannels = 0;
if(!tHasStarted) {
tHasStarted = true;
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_LEDC_CLK_EN);
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_LEDC_RST);
LEDC.conf.apb_clk_sel = 1;//LS use apb clock
addApbChangeCallback((void*)&_activeChannels, _on_apb_change);
#if !CONFIG_DISABLE_HAL_LOCKS
_ledc_sys_lock = xSemaphoreCreateMutex();
#endif
}
LEDC_MUTEX_LOCK();
LEDC_TIMER(group, timer).conf.clock_divider = div_num;//18 bit (10.8) This register is used to configure parameter for divider in timer the least significant eight bits represent the decimal part.
LEDC_TIMER(group, timer).conf.duty_resolution = bit_num;//5 bit This register controls the range of the counter in timer. the counter range is [0 2**bit_num] the max bit width for counter is 20.
LEDC_TIMER(group, timer).conf.tick_sel = apb_clk;//apb clock
#if CONFIG_IDF_TARGET_ESP32
if(group) {
#endif
LEDC_TIMER(group, timer).conf.low_speed_update = 1;//This bit is only useful for low speed timer channels, reserved for high speed timers
#if CONFIG_IDF_TARGET_ESP32
}
#endif
LEDC_TIMER(group, timer).conf.pause = 0;
LEDC_TIMER(group, timer).conf.rst = 1;//This bit is used to reset timer the counter will be 0 after reset.
LEDC_TIMER(group, timer).conf.rst = 0;
LEDC_MUTEX_UNLOCK();
_activeChannels |= (1 << chan); // mark as active for APB callback
}
//max div_num 0x3FFFF (262143)
//max bit_num 0x1F (31)
static double _ledcSetupTimerFreq(uint8_t chan, double freq, uint8_t bit_num)
{
uint64_t clk_freq = getApbFrequency();
clk_freq <<= 8;//div_num is 8 bit decimal
uint32_t div_num = (clk_freq >> bit_num) / freq;
bool apb_clk = true;
if(div_num > LEDC_DIV_NUM_HSTIMER0_V) {
clk_freq /= 80;
div_num = (clk_freq >> bit_num) / freq;
if(div_num > LEDC_DIV_NUM_HSTIMER0_V) {
div_num = LEDC_DIV_NUM_HSTIMER0_V;//lowest clock possible
}
apb_clk = false;
} else if(div_num < 256) {
div_num = 256;//highest clock possible
}
_ledcSetupTimer(chan, div_num, bit_num, apb_clk);
//log_i("Fin: %f, Fclk: %uMhz, bits: %u, DIV: %u, Fout: %f",
// freq, apb_clk?80:1, bit_num, div_num, (clk_freq >> bit_num) / (double)div_num);
return (clk_freq >> bit_num) / (double)div_num;
}
static double _ledcTimerRead(uint8_t chan)
{
uint32_t div_num;
uint8_t bit_num;
bool apb_clk;
uint8_t group=(chan/8), timer=((chan/2)%4);
LEDC_MUTEX_LOCK();
div_num = LEDC_TIMER(group, timer).conf.clock_divider;//18 bit (10.8) This register is used to configure parameter for divider in timer the least significant eight bits represent the decimal part.
bit_num = LEDC_TIMER(group, timer).conf.duty_resolution;//5 bit This register controls the range of the counter in timer. the counter range is [0 2**bit_num] the max bit width for counter is 20.
apb_clk = LEDC_TIMER(group, timer).conf.tick_sel;//apb clock
LEDC_MUTEX_UNLOCK();
uint64_t clk_freq = 1000000;
if(apb_clk) {
clk_freq = getApbFrequency();
}
clk_freq <<= 8;//div_num is 8 bit decimal
return (clk_freq >> bit_num) / (double)div_num;
}
static void _ledcSetupChannel(uint8_t chan, uint8_t idle_level)
{
uint8_t group=(chan/8), channel=(chan%8), timer=((chan/2)%4);
LEDC_MUTEX_LOCK();
LEDC_CHAN(group, channel).conf0.timer_sel = timer;//2 bit Selects the timer to attach 0-3
LEDC_CHAN(group, channel).conf0.idle_lv = idle_level;//1 bit This bit is used to control the output value when channel is off.
LEDC_CHAN(group, channel).hpoint.hpoint = 0;//20 bit The output value changes to high when timer selected by channel has reached hpoint
LEDC_CHAN(group, channel).conf1.duty_inc = 1;//1 bit This register is used to increase the duty of output signal or decrease the duty of output signal for high speed channel
LEDC_CHAN(group, channel).conf1.duty_num = 1;//10 bit This register is used to control the number of increased or decreased times for channel
LEDC_CHAN(group, channel).conf1.duty_cycle = 1;//10 bit This register is used to increase or decrease the duty every duty_cycle cycles for channel
LEDC_CHAN(group, channel).conf1.duty_scale = 0;//10 bit This register controls the increase or decrease step scale for channel.
LEDC_CHAN(group, channel).duty.duty = 0;
LEDC_CHAN(group, channel).conf0.sig_out_en = 0;//This is the output enable control bit for channel
LEDC_CHAN(group, channel).conf1.duty_start = 0;//When duty_num duty_cycle and duty_scale has been configured. these register won't take effect until set duty_start. this bit is automatically cleared by hardware.
#if CONFIG_IDF_TARGET_ESP32
if(group) {
#endif
LEDC_CHAN(group, channel).conf0.low_speed_update = 1;
#if CONFIG_IDF_TARGET_ESP32
} else {
LEDC_CHAN(group, channel).conf0.clk_en = 0;
}
#endif
LEDC_MUTEX_UNLOCK();
}
double ledcSetup(uint8_t chan, double freq, uint8_t bit_num)
{
if(chan > LAST_CHAN) {
return 0;
}
double res_freq = _ledcSetupTimerFreq(chan, freq, bit_num);
_ledcSetupChannel(chan, LOW);
return res_freq;
}
void ledcWrite(uint8_t chan, uint32_t duty)
{
if(chan > LAST_CHAN) {
return;
}
uint8_t group=(chan/8), channel=(chan%8);
LEDC_MUTEX_LOCK();
LEDC_CHAN(group, channel).duty.duty = duty << 4;//25 bit (21.4)
if(duty) {
LEDC_CHAN(group, channel).conf0.sig_out_en = 1;//This is the output enable control bit for channel
LEDC_CHAN(group, channel).conf1.duty_start = 1;//When duty_num duty_cycle and duty_scale has been configured. these register won't take effect until set duty_start. this bit is automatically cleared by hardware.
#if CONFIG_IDF_TARGET_ESP32
if(group) {
#endif
LEDC_CHAN(group, channel).conf0.low_speed_update = 1;
#if CONFIG_IDF_TARGET_ESP32
} else {
LEDC_CHAN(group, channel).conf0.clk_en = 1;
}
#endif
} else {
LEDC_CHAN(group, channel).conf0.sig_out_en = 0;//This is the output enable control bit for channel
LEDC_CHAN(group, channel).conf1.duty_start = 0;//When duty_num duty_cycle and duty_scale has been configured. these register won't take effect until set duty_start. this bit is automatically cleared by hardware.
#if CONFIG_IDF_TARGET_ESP32
if(group) {
#endif
LEDC_CHAN(group, channel).conf0.low_speed_update = 1;
#if CONFIG_IDF_TARGET_ESP32
} else {
LEDC_CHAN(group, channel).conf0.clk_en = 0;
}
#endif
}
LEDC_MUTEX_UNLOCK();
}
uint32_t ledcRead(uint8_t chan)
{
if(chan > LAST_CHAN) {
return 0;
}
return LEDC.channel_group[chan/8].channel[chan%8].duty.duty >> 4;
}
double ledcReadFreq(uint8_t chan)
{
if(!ledcRead(chan)){
return 0;
}
return _ledcTimerRead(chan);
}
double ledcWriteTone(uint8_t chan, double freq)
{
if(chan > LAST_CHAN) {
return 0;
}
if(!freq) {
ledcWrite(chan, 0);
return 0;
}
double res_freq = _ledcSetupTimerFreq(chan, freq, 10);
ledcWrite(chan, 0x1FF);
return res_freq;
}
double ledcWriteNote(uint8_t chan, 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;
}
double noteFreq = (double)noteFrequencyBase[note] / (double)(1 << (8-octave));
return ledcWriteTone(chan, noteFreq);
}
void ledcAttachPin(uint8_t pin, uint8_t chan)
{
if(chan > LAST_CHAN) {
return;
}
pinMode(pin, OUTPUT);
#if CONFIG_IDF_TARGET_ESP32S2
pinMatrixOutAttach(pin, LEDC_LS_SIG_OUT0_IDX + chan, false, false);
#else
pinMatrixOutAttach(pin, ((chan/8)?LEDC_LS_SIG_OUT0_IDX:LEDC_HS_SIG_OUT0_IDX) + (chan%8), false, false);
#endif
}
void ledcDetachPin(uint8_t pin)
{
pinMatrixOutDetach(pin, false, false);
}

View File

@ -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_LEDC_H_
#define _ESP32_HAL_LEDC_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stdbool.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;
//channel 0-15 resolution 1-16bits freq limits depend on resolution
double ledcSetup(uint8_t channel, double freq, uint8_t resolution_bits);
void ledcWrite(uint8_t channel, uint32_t duty);
double ledcWriteTone(uint8_t channel, double freq);
double ledcWriteNote(uint8_t channel, note_t note, uint8_t octave);
uint32_t ledcRead(uint8_t channel);
double ledcReadFreq(uint8_t channel);
void ledcAttachPin(uint8_t pin, uint8_t channel);
void ledcDetachPin(uint8_t pin);
#ifdef __cplusplus
}
#endif
#endif /* _ESP32_HAL_LEDC_H_ */

View File

@ -45,22 +45,6 @@
#include "rom/rtc.h"
#endif
//Undocumented!!! Get chip temperature in Farenheit
//Source: https://github.com/pcbreflux/espressif/blob/master/esp32/arduino/sketchbook/ESP32_int_temp_sensor/ESP32_int_temp_sensor.ino
uint8_t temprature_sens_read();
float temperatureRead()
{
return (temprature_sens_read() - 32) / 1.8;
}
void __yield()
{
vPortYield();
}
void yield() __attribute__ ((weak, alias("__yield")));
unsigned long ARDUINO_ISR_ATTR micros()
{
return (unsigned long) (esp_timer_get_time());

View File

@ -1,138 +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.h"
#include <stdbool.h>
#include <stddef.h>
#if CONFIG_SPIRAM_SUPPORT || CONFIG_SPIRAM
#include "soc/efuse_reg.h"
#include "esp_heap_caps.h"
#include "esp_system.h"
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
#include "esp32/spiram.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/spiram.h"
#include "esp32s2/rom/cache.h"
#else
#error Target CONFIG_IDF_TARGET is not supported
#endif
#else // ESP32 Before IDF 4.0
#include "esp_spiram.h"
#endif
static volatile bool spiramDetected = false;
static volatile bool spiramFailed = false;
bool psramInit(){
if (spiramDetected) {
return true;
}
#ifndef CONFIG_SPIRAM_BOOT_INIT
if (spiramFailed) {
return false;
}
#if CONFIG_IDF_TARGET_ESP32
uint32_t chip_ver = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_PKG);
uint32_t pkg_ver = chip_ver & 0x7;
if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5 || pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2) {
spiramFailed = true;
log_w("PSRAM not supported!");
return false;
}
#elif CONFIG_IDF_TARGET_ESP32S2
extern void esp_config_data_cache_mode(void);
esp_config_data_cache_mode();
Cache_Enable_DCache(0);
#endif
if (esp_spiram_init() != ESP_OK) {
spiramFailed = true;
log_w("PSRAM init failed!");
#if CONFIG_IDF_TARGET_ESP32
pinMatrixOutDetach(16, false, false);
pinMatrixOutDetach(17, false, false);
#endif
return false;
}
esp_spiram_init_cache();
if (!esp_spiram_test()) {
spiramFailed = true;
log_e("PSRAM test failed!");
return false;
}
if (esp_spiram_add_to_heapalloc() != ESP_OK) {
spiramFailed = true;
log_e("PSRAM could not be added to the heap!");
return false;
}
#if CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL && !CONFIG_ARDUINO_ISR_IRAM
heap_caps_malloc_extmem_enable(CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL);
#endif
#endif
spiramDetected = true;
log_d("PSRAM enabled");
return true;
}
bool ARDUINO_ISR_ATTR psramFound(){
return spiramDetected;
}
void ARDUINO_ISR_ATTR *ps_malloc(size_t size){
if(!spiramDetected){
return NULL;
}
return heap_caps_malloc(size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
}
void ARDUINO_ISR_ATTR *ps_calloc(size_t n, size_t size){
if(!spiramDetected){
return NULL;
}
return heap_caps_calloc(n, size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
}
void ARDUINO_ISR_ATTR *ps_realloc(void *ptr, size_t size){
if(!spiramDetected){
return NULL;
}
return heap_caps_realloc(ptr, size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
}
#else
bool psramInit(){
return false;
}
bool ARDUINO_ISR_ATTR psramFound(){
return false;
}
void ARDUINO_ISR_ATTR *ps_malloc(size_t size){
return NULL;
}
void ARDUINO_ISR_ATTR *ps_calloc(size_t n, size_t size){
return NULL;
}
void ARDUINO_ISR_ATTR *ps_realloc(void *ptr, size_t size){
return NULL;
}
#endif

View File

@ -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_ */

View File

@ -1,878 +0,0 @@
// Copyright 2018 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 "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
#include "freertos/semphr.h"
#include "esp32-hal.h"
#include "esp32-hal-log.h"
#include "esp8266-compat.h"
#include "soc/gpio_reg.h"
#include "soc/rmt_struct.h"
#include "driver/periph_ctrl.h"
#include "esp_intr_alloc.h"
#include "hal/rmt_ll.h"
#include "driver/rmt.h"
#include "esp32-hal-rmt.h"
#include "esp32-hal-gpio.h"
#include "esp32-hal-matrix.h"
// RMTMEM address is declared in <target>.peripherals.ld
extern rmt_mem_t RMTMEM;
/**
* Internal macros
*/
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
#define MAX_CHANNELS 8
#elif CONFIG_IDF_TARGET_ESP32S2
#define MAX_CHANNELS 4
#else
#error Target CONFIG_IDF_TARGET is not supported
#endif
#define MAX_DATA_PER_CHANNEL 64
#define MAX_DATA_PER_ITTERATION 62
#define _ABS(a) (a>0?a:-a)
#define _LIMIT(a,b) (a>b?b:a)
#define __INT_TX_END (1)
#define __INT_RX_END (2)
#define __INT_ERROR (4)
#define __INT_THR_EVNT (1<<24)
#define _INT_TX_END(channel) (__INT_TX_END<<(channel*3))
#define _INT_RX_END(channel) (__INT_RX_END<<(channel*3))
#define _INT_ERROR(channel) (__INT_ERROR<<(channel*3))
#define _INT_THR_EVNT(channel) ((__INT_THR_EVNT)<<(channel))
#if CONFIG_DISABLE_HAL_LOCKS
# define RMT_MUTEX_LOCK(channel)
# define RMT_MUTEX_UNLOCK(channel)
#else
# define RMT_MUTEX_LOCK(channel) do {} while (xSemaphoreTake(g_rmt_objlocks[channel], portMAX_DELAY) != pdPASS)
# define RMT_MUTEX_UNLOCK(channel) xSemaphoreGive(g_rmt_objlocks[channel])
#endif /* CONFIG_DISABLE_HAL_LOCKS */
#define _RMT_INTERNAL_DEBUG
#ifdef _RMT_INTERNAL_DEBUG
# define DEBUG_INTERRUPT_START(pin) digitalWrite(pin, 1);
# define DEBUG_INTERRUPT_END(pin) digitalWrite(pin, 0);
#else
# define DEBUG_INTERRUPT_START(pin)
# define DEBUG_INTERRUPT_END(pin)
#endif /* _RMT_INTERNAL_DEBUG */
/**
* Typedefs for internal stuctures, enums
*/
typedef enum {
E_NO_INTR = 0,
E_TX_INTR = 1,
E_TXTHR_INTR = 2,
E_RX_INTR = 4,
} intr_mode_t;
typedef enum {
E_INACTIVE = 0,
E_FIRST_HALF = 1,
E_LAST_DATA = 2,
E_END_TRANS = 4,
E_SET_CONTI = 8,
} transaction_state_t;
struct rmt_obj_s
{
bool allocated;
EventGroupHandle_t events;
int pin;
int channel;
bool tx_not_rx;
int buffers;
int data_size;
uint32_t* data_ptr;
intr_mode_t intr_mode;
transaction_state_t tx_state;
rmt_rx_data_cb_t cb;
bool data_alloc;
void * arg;
};
/**
* Internal variables for channel descriptors
*/
static SemaphoreHandle_t g_rmt_objlocks[MAX_CHANNELS] = {
NULL, NULL, NULL, NULL,
#if CONFIG_IDF_TARGET_ESP32
NULL, NULL, NULL, NULL
#endif
};
static rmt_obj_t g_rmt_objects[MAX_CHANNELS] = {
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false, NULL},
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false, NULL},
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false, NULL},
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false, NULL},
#if CONFIG_IDF_TARGET_ESP32
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false, NULL},
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false, NULL},
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false, NULL},
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false, NULL},
#endif
};
/**
* Internal variables for driver data
*/
static intr_handle_t intr_handle;
static bool periph_enabled = false;
static SemaphoreHandle_t g_rmt_block_lock = NULL;
/**
* Internal method (private) declarations
*/
static void _initPin(int pin, int channel, bool tx_not_rx);
static bool _rmtSendOnce(rmt_obj_t* rmt, rmt_data_t* data, size_t size, bool continuous);
static void ARDUINO_ISR_ATTR _rmt_isr(void* arg);
static rmt_obj_t* _rmtAllocate(int pin, int from, int size);
static void _initPin(int pin, int channel, bool tx_not_rx);
static int ARDUINO_ISR_ATTR _rmt_get_mem_len(uint8_t channel);
static void ARDUINO_ISR_ATTR _rmt_tx_mem_first(uint8_t ch);
static void ARDUINO_ISR_ATTR _rmt_tx_mem_second(uint8_t ch);
/**
* Public method definitions
*/
bool rmtSetCarrier(rmt_obj_t* rmt, bool carrier_en, bool carrier_level, uint32_t low, uint32_t high)
{
if (!rmt || low > 0xFFFF || high > 0xFFFF) {
return false;
}
size_t channel = rmt->channel;
RMT_MUTEX_LOCK(channel);
RMT.carrier_duty_ch[channel].low = low;
RMT.carrier_duty_ch[channel].high = high;
RMT.conf_ch[channel].conf0.carrier_en = carrier_en;
RMT.conf_ch[channel].conf0.carrier_out_lv = carrier_level;
RMT_MUTEX_UNLOCK(channel);
return true;
}
bool rmtSetFilter(rmt_obj_t* rmt, bool filter_en, uint32_t filter_level)
{
if (!rmt || filter_level > 0xFF) {
return false;
}
size_t channel = rmt->channel;
RMT_MUTEX_LOCK(channel);
RMT.conf_ch[channel].conf1.rx_filter_thres = filter_level;
RMT.conf_ch[channel].conf1.rx_filter_en = filter_en;
RMT_MUTEX_UNLOCK(channel);
return true;
}
bool rmtSetRxThreshold(rmt_obj_t* rmt, uint32_t value)
{
if (!rmt || value > 0xFFFF) {
return false;
}
size_t channel = rmt->channel;
RMT_MUTEX_LOCK(channel);
RMT.conf_ch[channel].conf0.idle_thres = value;
RMT_MUTEX_UNLOCK(channel);
return true;
}
bool rmtDeinit(rmt_obj_t *rmt)
{
if (!rmt) {
return false;
}
// sanity check
if (rmt != &(g_rmt_objects[rmt->channel])) {
return false;
}
size_t from = rmt->channel;
size_t to = rmt->buffers + rmt->channel;
size_t i;
#if !CONFIG_DISABLE_HAL_LOCKS
if(g_rmt_objlocks[from] != NULL) {
vSemaphoreDelete(g_rmt_objlocks[from]);
}
#endif
if (g_rmt_objects[from].data_alloc) {
free(g_rmt_objects[from].data_ptr);
}
for (i = from; i < to; i++) {
g_rmt_objects[i].allocated = false;
}
g_rmt_objects[from].channel = 0;
g_rmt_objects[from].buffers = 0;
return true;
}
bool rmtLoop(rmt_obj_t* rmt, rmt_data_t* data, size_t size)
{
if (!rmt) {
return false;
}
int allocated_size = MAX_DATA_PER_CHANNEL * rmt->buffers;
if (size > allocated_size) {
return false;
}
return _rmtSendOnce(rmt, data, size, true);
}
bool rmtWrite(rmt_obj_t* rmt, rmt_data_t* data, size_t size)
{
if (!rmt) {
return false;
}
int channel = rmt->channel;
int allocated_size = MAX_DATA_PER_CHANNEL * rmt->buffers;
if (size > allocated_size) {
int half_tx_nr = MAX_DATA_PER_ITTERATION/2;
RMT_MUTEX_LOCK(channel);
// setup interrupt handler if not yet installed for half and full tx
if (!intr_handle) {
esp_intr_alloc(ETS_RMT_INTR_SOURCE, (int)ARDUINO_ISR_FLAG, _rmt_isr, NULL, &intr_handle);
}
rmt->data_size = size - MAX_DATA_PER_ITTERATION;
rmt->data_ptr = ((uint32_t*)data) + MAX_DATA_PER_ITTERATION;
rmt->intr_mode = E_TX_INTR | E_TXTHR_INTR;
rmt->tx_state = E_SET_CONTI | E_FIRST_HALF;
// init the tx limit for interruption
RMT.tx_lim_ch[channel].limit = half_tx_nr+2;
// reset memory pointer
RMT.conf_ch[channel].conf1.apb_mem_rst = 1;
RMT.conf_ch[channel].conf1.apb_mem_rst = 0;
RMT.conf_ch[channel].conf1.mem_rd_rst = 1;
RMT.conf_ch[channel].conf1.mem_rd_rst = 0;
RMT.conf_ch[channel].conf1.mem_wr_rst = 1;
RMT.conf_ch[channel].conf1.mem_wr_rst = 0;
// set the tx end mark
RMTMEM.chan[channel].data32[MAX_DATA_PER_ITTERATION].val = 0;
// clear and enable both Tx completed and half tx event
RMT.int_clr.val = _INT_TX_END(channel);
RMT.int_clr.val = _INT_THR_EVNT(channel);
RMT.int_clr.val = _INT_ERROR(channel);
RMT.int_ena.val |= _INT_TX_END(channel);
RMT.int_ena.val |= _INT_THR_EVNT(channel);
RMT.int_ena.val |= _INT_ERROR(channel);
RMT_MUTEX_UNLOCK(channel);
// start the transation
return _rmtSendOnce(rmt, data, MAX_DATA_PER_ITTERATION, false);
} else {
// use one-go mode if data fits one buffer
return _rmtSendOnce(rmt, data, size, false);
}
}
bool rmtReadData(rmt_obj_t* rmt, uint32_t* data, size_t size)
{
if (!rmt) {
return false;
}
int channel = rmt->channel;
if (g_rmt_objects[channel].buffers < size/MAX_DATA_PER_CHANNEL) {
return false;
}
size_t i;
volatile uint32_t* rmt_mem_ptr = &(RMTMEM.chan[channel].data32[0].val);
for (i=0; i<size; i++) {
data[i] = *rmt_mem_ptr++;
}
return true;
}
bool rmtBeginReceive(rmt_obj_t* rmt)
{
if (!rmt) {
return false;
}
int channel = rmt->channel;
RMT.int_clr.val = _INT_ERROR(channel);
RMT.int_ena.val |= _INT_ERROR(channel);
RMT.conf_ch[channel].conf1.mem_owner = 1;
RMT.conf_ch[channel].conf1.mem_wr_rst = 1;
RMT.conf_ch[channel].conf1.rx_en = 1;
return true;
}
bool rmtReceiveCompleted(rmt_obj_t* rmt)
{
if (!rmt) {
return false;
}
int channel = rmt->channel;
if (RMT.int_raw.val&_INT_RX_END(channel)) {
// RX end flag
RMT.int_clr.val = _INT_RX_END(channel);
return true;
} else {
return false;
}
}
bool rmtRead(rmt_obj_t* rmt, rmt_rx_data_cb_t cb, void * arg)
{
if (!rmt && !cb) {
return false;
}
int channel = rmt->channel;
RMT_MUTEX_LOCK(channel);
rmt->arg = arg;
rmt->intr_mode = E_RX_INTR;
rmt->tx_state = E_FIRST_HALF;
rmt->cb = cb;
// allocate internally two buffers which would alternate
if (!rmt->data_alloc) {
rmt->data_ptr = (uint32_t*)malloc(2*MAX_DATA_PER_CHANNEL*(rmt->buffers)*sizeof(uint32_t));
rmt->data_size = MAX_DATA_PER_CHANNEL*rmt->buffers;
rmt->data_alloc = true;
}
RMT.conf_ch[channel].conf1.mem_owner = 1;
RMT.int_clr.val = _INT_RX_END(channel);
RMT.int_clr.val = _INT_ERROR(channel);
RMT.int_ena.val |= _INT_RX_END(channel);
RMT.int_ena.val |= _INT_ERROR(channel);
RMT.conf_ch[channel].conf1.mem_wr_rst = 1;
RMT.conf_ch[channel].conf1.rx_en = 1;
RMT_MUTEX_UNLOCK(channel);
return true;
}
bool rmtEnd(rmt_obj_t* rmt) {
if (!rmt) {
return false;
}
int channel = rmt->channel;
RMT_MUTEX_LOCK(channel);
RMT.conf_ch[channel].conf1.rx_en = 1;
RMT_MUTEX_UNLOCK(channel);
return true;
}
bool rmtReadAsync(rmt_obj_t* rmt, rmt_data_t* data, size_t size, void* eventFlag, bool waitForData, uint32_t timeout)
{
if (!rmt) {
return false;
}
int channel = rmt->channel;
if (g_rmt_objects[channel].buffers < size/MAX_DATA_PER_CHANNEL) {
return false;
}
if (eventFlag) {
xEventGroupClearBits(eventFlag, RMT_FLAGS_ALL);
rmt->events = eventFlag;
}
if (data && size>0) {
rmt->data_ptr = (uint32_t*)data;
rmt->data_size = size;
}
RMT_MUTEX_LOCK(channel);
rmt->intr_mode = E_RX_INTR;
RMT.conf_ch[channel].conf1.mem_owner = 1;
RMT.int_clr.val = _INT_RX_END(channel);
RMT.int_clr.val = _INT_ERROR(channel);
RMT.int_ena.val |= _INT_RX_END(channel);
RMT.int_ena.val |= _INT_ERROR(channel);
RMT.conf_ch[channel].conf1.mem_wr_rst = 1;
RMT.conf_ch[channel].conf1.rx_en = 1;
RMT_MUTEX_UNLOCK(channel);
// wait for data if requested so
if (waitForData && eventFlag) {
uint32_t flags = xEventGroupWaitBits(eventFlag, RMT_FLAGS_ALL,
pdTRUE /* clear on exit */, pdFALSE /* wait for all bits */, timeout);
if (flags & RMT_FLAG_ERROR) {
return false;
}
}
return true;
}
float rmtSetTick(rmt_obj_t* rmt, float tick)
{
if (!rmt) {
return false;
}
/*
divider field span from 1 (smallest), 2, 3, ... , 0xFF, 0x00 (highest)
* rmt tick from 1/80M -> 12.5ns (1x) div_cnt = 0x01
3.2 us (256x) div_cnt = 0x00
* rmt tick for 1 MHz -> 1us (1x) div_cnt = 0x01
256us (256x) div_cnt = 0x00
*/
int apb_div = _LIMIT(tick/12.5, 256);
int ref_div = _LIMIT(tick/1000, 256);
float apb_tick = 12.5 * apb_div;
float ref_tick = 1000.0 * ref_div;
size_t channel = rmt->channel;
if (_ABS(apb_tick - tick) < _ABS(ref_tick - tick)) {
RMT.conf_ch[channel].conf0.div_cnt = apb_div & 0xFF;
RMT.conf_ch[channel].conf1.ref_always_on = 1;
return apb_tick;
} else {
RMT.conf_ch[channel].conf0.div_cnt = ref_div & 0xFF;
RMT.conf_ch[channel].conf1.ref_always_on = 0;
return ref_tick;
}
}
rmt_obj_t* rmtInit(int pin, bool tx_not_rx, rmt_reserve_memsize_t memsize)
{
int buffers = memsize;
rmt_obj_t* rmt;
size_t i;
size_t j;
// create common block mutex for protecting allocs from multiple threads
if (!g_rmt_block_lock) {
g_rmt_block_lock = xSemaphoreCreateMutex();
}
// lock
while (xSemaphoreTake(g_rmt_block_lock, portMAX_DELAY) != pdPASS) {}
for (i=0; i<MAX_CHANNELS; i++) {
for (j=0; j<buffers && i+j < MAX_CHANNELS; j++) {
// if the space is ocupied break and continue on other channel
if (g_rmt_objects[i+j].allocated) {
i += j; // continue searching from latter channel
break;
}
}
if (j == buffers) {
// found a space in channel descriptors
break;
}
}
if (i == MAX_CHANNELS || i+j > MAX_CHANNELS || j != buffers) {
xSemaphoreGive(g_rmt_block_lock);
return NULL;
}
rmt = _rmtAllocate(pin, i, buffers);
xSemaphoreGive(g_rmt_block_lock);
size_t channel = i;
#if !CONFIG_DISABLE_HAL_LOCKS
if(g_rmt_objlocks[channel] == NULL) {
g_rmt_objlocks[channel] = xSemaphoreCreateMutex();
if(g_rmt_objlocks[channel] == NULL) {
return NULL;
}
}
#endif
RMT_MUTEX_LOCK(channel);
rmt->pin = pin;
rmt->tx_not_rx = tx_not_rx;
rmt->buffers =buffers;
rmt->channel = channel;
rmt->arg = NULL;
_initPin(pin, channel, tx_not_rx);
// Initialize the registers in default mode:
// - no carrier, filter
// - timebase tick of 1us
// - idle threshold set to 0x8000 (max pulse width + 1)
RMT.conf_ch[channel].conf0.div_cnt = 1;
RMT.conf_ch[channel].conf0.mem_size = buffers;
RMT.conf_ch[channel].conf0.carrier_en = 0;
RMT.conf_ch[channel].conf0.carrier_out_lv = 0;
#if CONFIG_IDF_TARGET_ESP32
RMT.conf_ch[channel].conf0.mem_pd = 0;
#endif
RMT.conf_ch[channel].conf0.idle_thres = 0x80;
RMT.conf_ch[channel].conf1.rx_en = 0;
RMT.conf_ch[channel].conf1.tx_conti_mode = 0;
#if CONFIG_IDF_TARGET_ESP32
RMT.conf_ch[channel].conf1.ref_cnt_rst = 0;
#else
RMT.conf_ch[channel].conf1.chk_rx_carrier_en = 0;
#endif
RMT.conf_ch[channel].conf1.rx_filter_en = 0;
RMT.conf_ch[channel].conf1.rx_filter_thres = 0;
RMT.conf_ch[channel].conf1.idle_out_lv = 0; // signal level for idle
RMT.conf_ch[channel].conf1.idle_out_en = 1; // enable idle
RMT.conf_ch[channel].conf1.ref_always_on = 0; // base clock
RMT.apb_conf.fifo_mask = 1;
if (tx_not_rx) {
// RMT.conf_ch[channel].conf1.rx_en = 0;
RMT.conf_ch[channel].conf1.mem_owner = 0;
RMT.conf_ch[channel].conf1.mem_rd_rst = 1;
} else {
// RMT.conf_ch[channel].conf1.rx_en = 1;
RMT.conf_ch[channel].conf1.mem_owner = 1;
RMT.conf_ch[channel].conf1.mem_wr_rst = 1;
}
// install interrupt if at least one channel is active
if (!intr_handle) {
esp_intr_alloc(ETS_RMT_INTR_SOURCE, (int)ARDUINO_ISR_FLAG, _rmt_isr, NULL, &intr_handle);
}
RMT_MUTEX_UNLOCK(channel);
return rmt;
}
/**
* Private methods definitions
*/
bool _rmtSendOnce(rmt_obj_t* rmt, rmt_data_t* data, size_t size, bool continuous)
{
if (!rmt) {
return false;
}
int channel = rmt->channel;
RMT.apb_conf.fifo_mask = 1;
if (data && size>0) {
size_t i;
volatile uint32_t* rmt_mem_ptr = &(RMTMEM.chan[channel].data32[0].val);
for (i = 0; i < size; i++) {
*rmt_mem_ptr++ = data[i].val;
}
// tx end mark
RMTMEM.chan[channel].data32[size].val = 0;
}
RMT_MUTEX_LOCK(channel);
RMT.conf_ch[channel].conf1.tx_conti_mode = continuous;
RMT.conf_ch[channel].conf1.mem_rd_rst = 1;
RMT.conf_ch[channel].conf1.tx_start = 1;
RMT_MUTEX_UNLOCK(channel);
return true;
}
static rmt_obj_t* _rmtAllocate(int pin, int from, int size)
{
size_t i;
// setup how many buffers shall we use
g_rmt_objects[from].buffers = size;
for (i=0; i<size; i++) {
// mark the block of channels as used
g_rmt_objects[i+from].allocated = true;
}
return &(g_rmt_objects[from]);
}
static void _initPin(int pin, int channel, bool tx_not_rx)
{
if (!periph_enabled) {
periph_enabled = true;
periph_module_enable( PERIPH_RMT_MODULE );
}
if (tx_not_rx) {
pinMode(pin, OUTPUT);
pinMatrixOutAttach(pin, RMT_SIG_OUT0_IDX + channel, 0, 0);
} else {
pinMode(pin, INPUT);
pinMatrixInAttach(pin, RMT_SIG_IN0_IDX + channel, 0);
}
}
static void ARDUINO_ISR_ATTR _rmt_isr(void* arg)
{
int intr_val = RMT.int_st.val;
size_t ch;
for (ch = 0; ch < MAX_CHANNELS; ch++) {
if (intr_val & _INT_RX_END(ch)) {
// clear the flag
RMT.int_clr.val = _INT_RX_END(ch);
RMT.int_ena.val &= ~_INT_RX_END(ch);
if ((g_rmt_objects[ch].intr_mode) & E_RX_INTR) {
if (g_rmt_objects[ch].events) {
xEventGroupSetBits(g_rmt_objects[ch].events, RMT_FLAG_RX_DONE);
}
if (g_rmt_objects[ch].data_ptr && g_rmt_objects[ch].data_size > 0) {
size_t i;
uint32_t * data = g_rmt_objects[ch].data_ptr;
// in case of callback, provide switching between memories
if (g_rmt_objects[ch].cb) {
if (g_rmt_objects[ch].tx_state & E_FIRST_HALF) {
g_rmt_objects[ch].tx_state &= ~E_FIRST_HALF;
} else {
g_rmt_objects[ch].tx_state |= E_FIRST_HALF;
data += MAX_DATA_PER_CHANNEL*(g_rmt_objects[ch].buffers);
}
}
uint32_t *data_received = data;
for (i = 0; i < g_rmt_objects[ch].data_size; i++ ) {
*data++ = RMTMEM.chan[ch].data32[i].val;
}
if (g_rmt_objects[ch].cb) {
// actually received data ptr
(g_rmt_objects[ch].cb)(data_received, _rmt_get_mem_len(ch), g_rmt_objects[ch].arg);
// restart the reception
RMT.conf_ch[ch].conf1.mem_owner = 1;
RMT.conf_ch[ch].conf1.mem_wr_rst = 1;
RMT.conf_ch[ch].conf1.rx_en = 1;
RMT.int_ena.val |= _INT_RX_END(ch);
} else {
// if not callback provide, expect only one Rx
g_rmt_objects[ch].intr_mode &= ~E_RX_INTR;
}
}
} else {
// Report error and disable Rx interrupt
log_e("Unexpected Rx interrupt!\n"); // TODO: eplace messages with log_X
RMT.int_ena.val &= ~_INT_RX_END(ch);
}
}
if (intr_val & _INT_ERROR(ch)) {
// clear the flag
RMT.int_clr.val = _INT_ERROR(ch);
RMT.int_ena.val &= ~_INT_ERROR(ch);
// report error
log_e("RMT Error %d!\n", ch);
if (g_rmt_objects[ch].events) {
xEventGroupSetBits(g_rmt_objects[ch].events, RMT_FLAG_ERROR);
}
// reset memory
RMT.conf_ch[ch].conf1.mem_rd_rst = 1;
RMT.conf_ch[ch].conf1.mem_rd_rst = 0;
RMT.conf_ch[ch].conf1.mem_wr_rst = 1;
RMT.conf_ch[ch].conf1.mem_wr_rst = 0;
}
if (intr_val & _INT_TX_END(ch)) {
RMT.int_clr.val = _INT_TX_END(ch);
_rmt_tx_mem_second(ch);
}
if (intr_val & _INT_THR_EVNT(ch)) {
// clear the flag
RMT.int_clr.val = _INT_THR_EVNT(ch);
// initial setup of continuous mode
if (g_rmt_objects[ch].tx_state & E_SET_CONTI) {
RMT.conf_ch[ch].conf1.tx_conti_mode = 1;
g_rmt_objects[ch].intr_mode &= ~E_SET_CONTI;
}
_rmt_tx_mem_first(ch);
}
}
}
static void ARDUINO_ISR_ATTR _rmt_tx_mem_second(uint8_t ch)
{
DEBUG_INTERRUPT_START(4)
uint32_t* data = g_rmt_objects[ch].data_ptr;
int half_tx_nr = MAX_DATA_PER_ITTERATION/2;
int i;
RMT.tx_lim_ch[ch].limit = half_tx_nr+2;
RMT.int_clr.val = _INT_THR_EVNT(ch);
RMT.int_ena.val |= _INT_THR_EVNT(ch);
g_rmt_objects[ch].tx_state |= E_FIRST_HALF;
if (data) {
int remaining_size = g_rmt_objects[ch].data_size;
// will the remaining data occupy the entire halfbuffer
if (remaining_size > half_tx_nr) {
for (i = 0; i < half_tx_nr; i++) {
RMTMEM.chan[ch].data32[half_tx_nr+i].val = data[i];
}
g_rmt_objects[ch].data_size -= half_tx_nr;
g_rmt_objects[ch].data_ptr += half_tx_nr;
} else {
for (i = 0; i < half_tx_nr; i++) {
if (i < remaining_size) {
RMTMEM.chan[ch].data32[half_tx_nr+i].val = data[i];
} else {
RMTMEM.chan[ch].data32[half_tx_nr+i].val = 0x000F000F;
}
}
g_rmt_objects[ch].data_ptr = NULL;
}
} else if ((!(g_rmt_objects[ch].tx_state & E_LAST_DATA)) &&
(!(g_rmt_objects[ch].tx_state & E_END_TRANS))) {
for (i = 0; i < half_tx_nr; i++) {
RMTMEM.chan[ch].data32[half_tx_nr+i].val = 0x000F000F;
}
RMTMEM.chan[ch].data32[half_tx_nr+i].val = 0;
g_rmt_objects[ch].tx_state |= E_LAST_DATA;
RMT.conf_ch[ch].conf1.tx_conti_mode = 0;
} else {
log_d("RMT Tx finished %d!\n", ch);
RMT.conf_ch[ch].conf1.tx_conti_mode = 0;
RMT.int_ena.val &= ~_INT_TX_END(ch);
RMT.int_ena.val &= ~_INT_THR_EVNT(ch);
g_rmt_objects[ch].intr_mode = E_NO_INTR;
g_rmt_objects[ch].tx_state = E_INACTIVE;
}
DEBUG_INTERRUPT_END(4);
}
static void ARDUINO_ISR_ATTR _rmt_tx_mem_first(uint8_t ch)
{
DEBUG_INTERRUPT_START(2);
uint32_t* data = g_rmt_objects[ch].data_ptr;
int half_tx_nr = MAX_DATA_PER_ITTERATION/2;
int i;
RMT.int_ena.val &= ~_INT_THR_EVNT(ch);
RMT.tx_lim_ch[ch].limit = 0;
if (data) {
int remaining_size = g_rmt_objects[ch].data_size;
// will the remaining data occupy the entire halfbuffer
if (remaining_size > half_tx_nr) {
RMTMEM.chan[ch].data32[0].val = data[0] - 1;
for (i = 1; i < half_tx_nr; i++) {
RMTMEM.chan[ch].data32[i].val = data[i];
}
g_rmt_objects[ch].tx_state &= ~E_FIRST_HALF;
// turn off the treshold interrupt
RMT.int_ena.val &= ~_INT_THR_EVNT(ch);
RMT.tx_lim_ch[ch].limit = 0;
g_rmt_objects[ch].data_size -= half_tx_nr;
g_rmt_objects[ch].data_ptr += half_tx_nr;
} else {
RMTMEM.chan[ch].data32[0].val = data[0] - 1;
for (i = 1; i < half_tx_nr; i++) {
if (i < remaining_size) {
RMTMEM.chan[ch].data32[i].val = data[i];
} else {
RMTMEM.chan[ch].data32[i].val = 0x000F000F;
}
}
g_rmt_objects[ch].tx_state &= ~E_FIRST_HALF;
g_rmt_objects[ch].data_ptr = NULL;
}
} else {
for (i = 0; i < half_tx_nr; i++) {
RMTMEM.chan[ch].data32[i].val = 0x000F000F;
}
RMTMEM.chan[ch].data32[i].val = 0;
g_rmt_objects[ch].tx_state &= ~E_FIRST_HALF;
RMT.tx_lim_ch[ch].limit = 0;
g_rmt_objects[ch].tx_state |= E_LAST_DATA;
RMT.conf_ch[ch].conf1.tx_conti_mode = 0;
}
DEBUG_INTERRUPT_END(2);
}
static int ARDUINO_ISR_ATTR _rmt_get_mem_len(uint8_t channel)
{
int block_num = RMT.conf_ch[channel].conf0.mem_size;
int item_block_len = block_num * 64;
volatile uint32_t* data = &RMTMEM.chan[channel].data32->val;
int idx;
for(idx = 0; idx < item_block_len; idx++) {
rmt_item32_t helper;
helper.val = data[idx];
if(helper.duration0 == 0) {
return idx;
} else if(helper.duration1 == 0) {
return idx + 1;
}
}
return idx;
}

View File

@ -1,152 +0,0 @@
// Copyright 2018 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_
#ifdef __cplusplus
extern "C" {
#endif
// notification flags
#define RMT_FLAG_TX_DONE (1)
#define RMT_FLAG_RX_DONE (2)
#define RMT_FLAG_ERROR (4)
#define RMT_FLAGS_ALL (RMT_FLAG_TX_DONE | RMT_FLAG_RX_DONE | RMT_FLAG_ERROR)
struct rmt_obj_s;
typedef enum {
RMT_MEM_64 = 1,
RMT_MEM_128 = 2,
RMT_MEM_192 = 3,
RMT_MEM_256 = 4,
RMT_MEM_320 = 5,
RMT_MEM_384 = 6,
RMT_MEM_448 = 7,
RMT_MEM_512 = 8,
} rmt_reserve_memsize_t;
typedef struct rmt_obj_s rmt_obj_t;
typedef void (*rmt_rx_data_cb_t)(uint32_t *data, size_t len, void *arg);
typedef struct {
union {
struct {
uint32_t duration0 :15;
uint32_t level0 :1;
uint32_t duration1 :15;
uint32_t level1 :1;
};
uint32_t val;
};
} rmt_data_t;
/**
* Initialize the object
*
*/
rmt_obj_t* rmtInit(int pin, bool tx_not_rx, rmt_reserve_memsize_t memsize);
/**
* Sets the clock/divider of timebase the nearest tick to the supplied value in nanoseconds
* return the real actual tick value in ns
*/
float rmtSetTick(rmt_obj_t* rmt, float tick);
/**
* Sending data in one-go mode or continual mode
* (more data being send while updating buffers in interrupts)
*
*/
bool rmtWrite(rmt_obj_t* rmt, rmt_data_t* data, size_t size);
/**
* Loop data up to the reserved memsize continuously
*
*/
bool rmtLoop(rmt_obj_t* rmt, rmt_data_t* data, size_t size);
/**
* Initiates async receive, event flag indicates data received
*
*/
bool rmtReadAsync(rmt_obj_t* rmt, rmt_data_t* data, size_t size, void* eventFlag, bool waitForData, uint32_t timeout);
/**
* Initiates async receive with automatic buffering
* and callback with data from ISR
*
*/
bool rmtRead(rmt_obj_t* rmt, rmt_rx_data_cb_t cb, void * arg);
/***
* Ends async receive started with rmtRead(); but does not
* rmtDeInit().
*/
bool rmtEnd(rmt_obj_t* rmt);
/* Additional interface */
/**
* Start reception
*
*/
bool rmtBeginReceive(rmt_obj_t* rmt);
/**
* Checks if reception completes
*
*/
bool rmtReceiveCompleted(rmt_obj_t* rmt);
/**
* Reads the data for particular channel
*
*/
bool rmtReadData(rmt_obj_t* rmt, uint32_t* data, size_t size);
/**
* Setting threshold for Rx completed
*/
bool rmtSetRxThreshold(rmt_obj_t* rmt, uint32_t value);
/**
* Setting carrier
*/
bool rmtSetCarrier(rmt_obj_t* rmt, bool carrier_en, bool carrier_level, uint32_t low, uint32_t high);
/**
* Setting input filter
*/
bool rmtSetFilter(rmt_obj_t* rmt, bool filter_en, uint32_t filter_level);
/**
* Deinitialize the driver
*/
bool rmtDeinit(rmt_obj_t *rmt);
// TODO:
// * uninstall interrupt when all channels are deinit
// * send only-conti mode with circular-buffer
// * put sanity checks to some macro or inlines
// * doxy comments
// * error reporting
#ifdef __cplusplus
}
#endif
#endif /* MAIN_ESP32_HAL_RMT_H_ */

View File

@ -1,133 +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.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "esp32-hal-matrix.h"
#include "soc/gpio_sd_reg.h"
#include "soc/gpio_sd_struct.h"
#include "freertos/semphr.h"
#include "esp32-hal-cpu.h"
#include "esp32-hal-gpio.h"
#include "esp_system.h"
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
#include "esp32/rom/ets_sys.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/rom/ets_sys.h"
#else
#error Target CONFIG_IDF_TARGET is not supported
#endif
#else // ESP32 Before IDF 4.0
#include "rom/ets_sys.h"
#endif
#if CONFIG_DISABLE_HAL_LOCKS
#define SD_MUTEX_LOCK()
#define SD_MUTEX_UNLOCK()
#else
#define SD_MUTEX_LOCK() do {} while (xSemaphoreTake(_sd_sys_lock, portMAX_DELAY) != pdPASS)
#define SD_MUTEX_UNLOCK() xSemaphoreGive(_sd_sys_lock)
SemaphoreHandle_t _sd_sys_lock;
#endif
static void _on_apb_change(void * arg, apb_change_ev_t ev_type, uint32_t old_apb, uint32_t new_apb){
if(old_apb == new_apb){
return;
}
uint32_t iarg = (uint32_t)arg;
uint8_t channel = iarg;
if(ev_type == APB_BEFORE_CHANGE){
SIGMADELTA.cg.clk_en = 0;
} else {
old_apb /= 1000000;
new_apb /= 1000000;
SD_MUTEX_LOCK();
uint32_t old_prescale = SIGMADELTA.channel[channel].prescale + 1;
SIGMADELTA.channel[channel].prescale = ((new_apb * old_prescale) / old_apb) - 1;
SIGMADELTA.cg.clk_en = 0;
SIGMADELTA.cg.clk_en = 1;
SD_MUTEX_UNLOCK();
}
}
uint32_t sigmaDeltaSetup(uint8_t channel, uint32_t freq) //chan 0-7 freq 1220-312500
{
if(channel > 7) {
return 0;
}
#if !CONFIG_DISABLE_HAL_LOCKS
static bool tHasStarted = false;
if(!tHasStarted) {
tHasStarted = true;
_sd_sys_lock = xSemaphoreCreateMutex();
}
#endif
uint32_t apb_freq = getApbFrequency();
uint32_t prescale = (apb_freq/(freq*256)) - 1;
if(prescale > 0xFF) {
prescale = 0xFF;
}
SD_MUTEX_LOCK();
#ifndef CONFIG_IDF_TARGET_ESP32
SIGMADELTA.misc.function_clk_en = 1;
#endif
SIGMADELTA.channel[channel].prescale = prescale;
SIGMADELTA.cg.clk_en = 0;
SIGMADELTA.cg.clk_en = 1;
SD_MUTEX_UNLOCK();
uint32_t iarg = channel;
addApbChangeCallback((void*)iarg, _on_apb_change);
return apb_freq/((prescale + 1) * 256);
}
void sigmaDeltaWrite(uint8_t channel, uint8_t duty) //chan 0-7 duty 8 bit
{
if(channel > 7) {
return;
}
duty -= 128;
SD_MUTEX_LOCK();
SIGMADELTA.channel[channel].duty = duty;
SD_MUTEX_UNLOCK();
}
uint8_t sigmaDeltaRead(uint8_t channel) //chan 0-7
{
if(channel > 7) {
return 0;
}
SD_MUTEX_LOCK();
uint8_t duty = SIGMADELTA.channel[channel].duty + 128;
SD_MUTEX_UNLOCK();
return duty;
}
void sigmaDeltaAttachPin(uint8_t pin, uint8_t channel) //channel 0-7
{
if(channel > 7) {
return;
}
pinMode(pin, OUTPUT);
pinMatrixOutAttach(pin, GPIO_SD0_OUT_IDX + channel, false, false);
}
void sigmaDeltaDetachPin(uint8_t pin)
{
pinMatrixOutDetach(pin, false, false);
}

View File

@ -1,37 +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_SD_H_
#define _ESP32_HAL_SD_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stdbool.h>
//channel 0-7 freq 1220-312500 duty 0-255
uint32_t sigmaDeltaSetup(uint8_t channel, uint32_t freq);
void sigmaDeltaWrite(uint8_t channel, uint8_t duty);
uint8_t sigmaDeltaRead(uint8_t channel);
void sigmaDeltaAttachPin(uint8_t pin, uint8_t channel);
void sigmaDeltaDetachPin(uint8_t pin);
#ifdef __cplusplus
}
#endif
#endif /* _ESP32_HAL_SD_H_ */

View File

@ -14,6 +14,10 @@
#include <string.h>
#include <driver/gpio.h>
#include <esp_log.h>
#define TAG "ARDUINO"
#include "esp32-hal-spi.h"
#include "esp32-hal.h"
#include "freertos/FreeRTOS.h"
@ -45,7 +49,6 @@
#include "rom/gpio.h"
#include "esp_intr.h"
#endif
#include "esp32-hal-gpio.h"
#include "esp32-hal-matrix.h"
#include "esp32-hal-cpu.h"
@ -146,7 +149,21 @@ void spiAttachSCK(spi_t * spi, int8_t sck)
}
#endif
}
pinMode(sck, OUTPUT);
{
const gpio_config_t config = {
.pin_bit_mask = 1ULL << sck,
.mode = GPIO_MODE_OUTPUT,
.pull_up_en = GPIO_PULLUP_DISABLE,
.pull_down_en = GPIO_PULLDOWN_DISABLE,
.intr_type = GPIO_INTR_DISABLE,
};
const int result = gpio_config(&config);
if (result != ESP_OK)
ESP_LOGE(TAG, "gpio_config() failed %s", esp_err_to_name(result));
}
pinMatrixOutAttach(sck, SPI_CLK_IDX(spi->num), false, false);
}
@ -174,7 +191,21 @@ void spiAttachMISO(spi_t * spi, int8_t miso)
#endif
}
SPI_MUTEX_LOCK();
pinMode(miso, INPUT);
{
const gpio_config_t config = {
.pin_bit_mask = (1ULL << miso),
.mode = GPIO_MODE_INPUT,
.pull_up_en = GPIO_PULLUP_DISABLE,
.pull_down_en = GPIO_PULLDOWN_DISABLE,
.intr_type = GPIO_INTR_DISABLE
};
const int result = gpio_config(&config);
if (result != ESP_OK)
ESP_LOGE(TAG, "gpio_config() failed %s", esp_err_to_name(result));
}
pinMatrixInAttach(miso, SPI_MISO_IDX(spi->num), false);
SPI_MUTEX_UNLOCK();
}
@ -202,7 +233,21 @@ void spiAttachMOSI(spi_t * spi, int8_t mosi)
}
#endif
}
pinMode(mosi, OUTPUT);
{
const gpio_config_t config = {
.pin_bit_mask = (1ULL << mosi),
.mode = GPIO_MODE_OUTPUT,
.pull_up_en = GPIO_PULLUP_DISABLE,
.pull_down_en = GPIO_PULLDOWN_DISABLE,
.intr_type = GPIO_INTR_DISABLE
};
const int result = gpio_config(&config);
if (result != ESP_OK)
ESP_LOGE(TAG, "gpio_config() failed %s", esp_err_to_name(result));
}
pinMatrixOutAttach(mosi, SPI_MOSI_IDX(spi->num), false, false);
}
@ -230,7 +275,19 @@ void spiDetachSCK(spi_t * spi, int8_t sck)
#endif
}
pinMatrixOutDetach(sck, false, false);
pinMode(sck, INPUT);
{
const gpio_config_t config = {
.pin_bit_mask = (1ULL << sck),
.mode = GPIO_MODE_INPUT,
.pull_up_en = GPIO_PULLUP_DISABLE,
.pull_down_en = GPIO_PULLDOWN_DISABLE,
.intr_type = GPIO_INTR_DISABLE
};
const int result = gpio_config(&config);
if (result != ESP_OK)
ESP_LOGE(TAG, "gpio_config() failed %s", esp_err_to_name(result));
}
}
void spiDetachMISO(spi_t * spi, int8_t miso)
@ -257,7 +314,19 @@ void spiDetachMISO(spi_t * spi, int8_t miso)
#endif
}
pinMatrixInDetach(SPI_MISO_IDX(spi->num), false, false);
pinMode(miso, INPUT);
{
const gpio_config_t config = {
.pin_bit_mask = (1ULL << miso),
.mode = GPIO_MODE_INPUT,
.pull_up_en = GPIO_PULLUP_DISABLE,
.pull_down_en = GPIO_PULLDOWN_DISABLE,
.intr_type = GPIO_INTR_DISABLE
};
const int result = gpio_config(&config);
if (result != ESP_OK)
ESP_LOGE(TAG, "gpio_config() failed %s", esp_err_to_name(result));
}
}
void spiDetachMOSI(spi_t * spi, int8_t mosi)
@ -284,7 +353,19 @@ void spiDetachMOSI(spi_t * spi, int8_t mosi)
#endif
}
pinMatrixOutDetach(mosi, false, false);
pinMode(mosi, INPUT);
{
const gpio_config_t config = {
.pin_bit_mask = (1ULL << mosi),
.mode = GPIO_MODE_INPUT,
.pull_up_en = GPIO_PULLUP_DISABLE,
.pull_down_en = GPIO_PULLDOWN_DISABLE,
.intr_type = GPIO_INTR_DISABLE
};
const int result = gpio_config(&config);
if (result != ESP_OK)
ESP_LOGE(TAG, "gpio_config() failed %s", esp_err_to_name(result));
}
}
void spiAttachSS(spi_t * spi, uint8_t cs_num, int8_t ss)
@ -314,7 +395,19 @@ void spiAttachSS(spi_t * spi, uint8_t cs_num, int8_t ss)
}
#endif
}
pinMode(ss, OUTPUT);
{
const gpio_config_t config = {
.pin_bit_mask = (1ULL << ss),
.mode = GPIO_MODE_OUTPUT,
.pull_up_en = GPIO_PULLUP_DISABLE,
.pull_down_en = GPIO_PULLDOWN_DISABLE,
.intr_type = GPIO_INTR_DISABLE
};
const int result = gpio_config(&config);
if (result != ESP_OK)
ESP_LOGE(TAG, "gpio_config() failed %s", esp_err_to_name(result));
}
pinMatrixOutAttach(ss, SPI_SS_IDX(spi->num, cs_num), false, false);
spiEnableSSPins(spi, (1 << cs_num));
}
@ -343,7 +436,19 @@ void spiDetachSS(spi_t * spi, int8_t ss)
#endif
}
pinMatrixOutDetach(ss, false, false);
pinMode(ss, INPUT);
{
const gpio_config_t config = {
.pin_bit_mask = (1ULL << ss),
.mode = GPIO_MODE_INPUT,
.pull_up_en = GPIO_PULLUP_DISABLE,
.pull_down_en = GPIO_PULLDOWN_DISABLE,
.intr_type = GPIO_INTR_DISABLE
};
const int result = gpio_config(&config);
if (result != ESP_OK)
ESP_LOGE(TAG, "gpio_config() failed %s", esp_err_to_name(result));
}
}
void spiEnableSSPins(spi_t * spi, uint8_t cs_mask)
@ -1278,7 +1383,7 @@ uint32_t spiFrequencyToClockDiv(uint32_t freq)
memcpy(&bestReg, &reg, sizeof(bestReg));
break;
} else if(calFreq < (int32_t) freq) {
if(abs(freq - calFreq) < abs(freq - bestFreq)) {
if(freq - calFreq < freq - bestFreq) {
bestFreq = calFreq;
memcpy(&bestReg, &reg, sizeof(bestReg));
}

View File

@ -1,697 +0,0 @@
#include "sdkconfig.h"
#if CONFIG_USB_ENABLED
#include <stdlib.h>
#include "esp_log.h"
#include "soc/soc.h"
#include "soc/efuse_reg.h"
#include "soc/rtc_cntl_reg.h"
#include "soc/usb_struct.h"
#include "soc/usb_reg.h"
#include "soc/usb_wrap_reg.h"
#include "soc/usb_wrap_struct.h"
#include "soc/periph_defs.h"
#include "soc/timer_group_struct.h"
#include "soc/system_reg.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "driver/periph_ctrl.h"
#include "esp_efuse.h"
#include "esp_efuse_table.h"
#include "tinyusb.h"
#include "esp32-hal.h"
#include "esp32-hal-tinyusb.h"
#include "esp32s2/rom/usb/usb_persist.h"
#include "esp32s2/rom/usb/usb_dc.h"
#include "esp32s2/rom/usb/chip_usb_dw_wrapper.h"
typedef char tusb_str_t[127];
static bool WEBUSB_ENABLED = false;
static tusb_str_t WEBUSB_URL = "";
static tusb_str_t USB_DEVICE_PRODUCT = "";
static tusb_str_t USB_DEVICE_MANUFACTURER = "";
static tusb_str_t USB_DEVICE_SERIAL = "";
static uint8_t USB_DEVICE_ATTRIBUTES = 0;
static uint16_t USB_DEVICE_POWER = 0;
/*
* Device Descriptor
* */
static tusb_desc_device_t tinyusb_device_descriptor = {
.bLength = sizeof(tusb_desc_device_t),
.bDescriptorType = TUSB_DESC_DEVICE,
.bcdUSB = 0,
.bDeviceClass = 0,
.bDeviceSubClass = 0,
.bDeviceProtocol = 0,
.bMaxPacketSize0 = CFG_TUD_ENDOINT0_SIZE,
.idVendor = 0,
.idProduct = 0,
.bcdDevice = 0,
.iManufacturer = 0x01,
.iProduct = 0x02,
.iSerialNumber = 0x03,
.bNumConfigurations = 0x01
};
/*
* String Descriptors
* */
#define MAX_STRING_DESCRIPTORS 20
static uint32_t tinyusb_string_descriptor_len = 4;
static char * tinyusb_string_descriptor[MAX_STRING_DESCRIPTORS] = {
// array of pointer to string descriptors
"\x09\x04", // 0: is supported language is English (0x0409)
USB_DEVICE_MANUFACTURER,// 1: Manufacturer
USB_DEVICE_PRODUCT, // 2: Product
USB_DEVICE_SERIAL, // 3: Serials, should use chip ID
};
/* Microsoft OS 2.0 registry property descriptor
Per MS requirements https://msdn.microsoft.com/en-us/library/windows/hardware/hh450799(v=vs.85).aspx
device should create DeviceInterfaceGUIDs. It can be done by driver and
in case of real PnP solution device should expose MS "Microsoft OS 2.0
registry property descriptor". Such descriptor can insert any record
into Windows registry per device/configuration/interface. In our case it
will insert "DeviceInterfaceGUIDs" multistring property.
GUID is freshly generated and should be OK to use.
https://developers.google.com/web/fundamentals/native-hardware/build-for-webusb/
(Section Microsoft OS compatibility descriptors)
*/
#define MS_OS_20_DESC_LEN 0xB2
static uint8_t const tinyusb_ms_os_20_descriptor[] =
{
// Set header: length, type, windows version, total length
U16_TO_U8S_LE(0x000A), U16_TO_U8S_LE(MS_OS_20_SET_HEADER_DESCRIPTOR), U32_TO_U8S_LE(0x06030000), U16_TO_U8S_LE(MS_OS_20_DESC_LEN),
// Configuration subset header: length, type, configuration index, reserved, configuration total length
U16_TO_U8S_LE(0x0008), U16_TO_U8S_LE(MS_OS_20_SUBSET_HEADER_CONFIGURATION), 0, 0, U16_TO_U8S_LE(MS_OS_20_DESC_LEN-0x0A),
// Function Subset header: length, type, first interface, reserved, subset length
U16_TO_U8S_LE(0x0008), U16_TO_U8S_LE(MS_OS_20_SUBSET_HEADER_FUNCTION), 0, 0, U16_TO_U8S_LE(MS_OS_20_DESC_LEN-0x0A-0x08),
// MS OS 2.0 Compatible ID descriptor: length, type, compatible ID, sub compatible ID
U16_TO_U8S_LE(0x0014), U16_TO_U8S_LE(MS_OS_20_FEATURE_COMPATBLE_ID), 'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // sub-compatible
// MS OS 2.0 Registry property descriptor: length, type
U16_TO_U8S_LE(MS_OS_20_DESC_LEN-0x0A-0x08-0x08-0x14), U16_TO_U8S_LE(MS_OS_20_FEATURE_REG_PROPERTY),
U16_TO_U8S_LE(0x0007), U16_TO_U8S_LE(0x002A), // wPropertyDataType, wPropertyNameLength and PropertyName "DeviceInterfaceGUIDs\0" in UTF-16
'D', 0x00, 'e', 0x00, 'v', 0x00, 'i', 0x00, 'c', 0x00, 'e', 0x00, 'I', 0x00, 'n', 0x00, 't', 0x00, 'e', 0x00,
'r', 0x00, 'f', 0x00, 'a', 0x00, 'c', 0x00, 'e', 0x00, 'G', 0x00, 'U', 0x00, 'I', 0x00, 'D', 0x00, 's', 0x00, 0x00, 0x00,
U16_TO_U8S_LE(0x0050), // wPropertyDataLength
//bPropertyData: “{975F44D9-0D08-43FD-8B3E-127CA8AFFF9D}”.
'{', 0x00, '9', 0x00, '7', 0x00, '5', 0x00, 'F', 0x00, '4', 0x00, '4', 0x00, 'D', 0x00, '9', 0x00, '-', 0x00,
'0', 0x00, 'D', 0x00, '0', 0x00, '8', 0x00, '-', 0x00, '4', 0x00, '3', 0x00, 'F', 0x00, 'D', 0x00, '-', 0x00,
'8', 0x00, 'B', 0x00, '3', 0x00, 'E', 0x00, '-', 0x00, '1', 0x00, '2', 0x00, '7', 0x00, 'C', 0x00, 'A', 0x00,
'8', 0x00, 'A', 0x00, 'F', 0x00, 'F', 0x00, 'F', 0x00, '9', 0x00, 'D', 0x00, '}', 0x00, 0x00, 0x00, 0x00, 0x00
};
TU_VERIFY_STATIC(sizeof(tinyusb_ms_os_20_descriptor) == MS_OS_20_DESC_LEN, "Incorrect size");
/*
* BOS Descriptor (required for webUSB)
* */
#define BOS_TOTAL_LEN (TUD_BOS_DESC_LEN + TUD_BOS_WEBUSB_DESC_LEN + TUD_BOS_MICROSOFT_OS_DESC_LEN)
enum {
VENDOR_REQUEST_WEBUSB = 1,
VENDOR_REQUEST_MICROSOFT = 2
};
static uint8_t const tinyusb_bos_descriptor[] = {
// total length, number of device caps
TUD_BOS_DESCRIPTOR(BOS_TOTAL_LEN, 2),
// Vendor Code, iLandingPage
TUD_BOS_WEBUSB_DESCRIPTOR(VENDOR_REQUEST_WEBUSB, 1),
// Microsoft OS 2.0 descriptor
TUD_BOS_MS_OS_20_DESCRIPTOR(MS_OS_20_DESC_LEN, VENDOR_REQUEST_MICROSOFT)
};
/*
* URL Descriptor (required for webUSB)
* */
typedef struct TU_ATTR_PACKED {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bScheme;
char url[127];
} tinyusb_desc_webusb_url_t;
static tinyusb_desc_webusb_url_t tinyusb_url_descriptor = {
.bLength = 3,
.bDescriptorType = 3, // WEBUSB URL type
.bScheme = 1, // URL Scheme Prefix: 0: "http://", 1: "https://", 255: ""
.url = ""
};
/*
* Configuration Descriptor
* */
static tinyusb_descriptor_cb_t tinyusb_loaded_interfaces_callbacks[USB_INTERFACE_MAX];
static uint32_t tinyusb_loaded_interfaces_mask = 0;
static uint8_t tinyusb_loaded_interfaces_num = 0;
static uint16_t tinyusb_config_descriptor_len = 0;
static uint8_t * tinyusb_config_descriptor = NULL;
/*
* Endpoint Usage Tracking
* */
typedef union {
struct {
uint32_t in:16;
uint32_t out:16;
};
uint32_t val;
} tinyusb_endpoints_usage_t;
static tinyusb_endpoints_usage_t tinyusb_endpoints;
/*
* TinyUSB Callbacks
* */
/**
* @brief Invoked when received GET CONFIGURATION DESCRIPTOR.
*/
uint8_t const *tud_descriptor_configuration_cb(uint8_t index)
{
//log_d("%u", index);
return tinyusb_config_descriptor;
}
/**
* @brief Invoked when received GET DEVICE DESCRIPTOR.
*/
uint8_t const *tud_descriptor_device_cb(void)
{
//log_d("");
return (uint8_t const *)&tinyusb_device_descriptor;
}
/**
* @brief Invoked when received GET STRING DESCRIPTOR request.
*/
uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid)
{
//log_d("%u (0x%x)", index, langid);
static uint16_t _desc_str[127];
uint8_t chr_count;
if (index == 0) {
memcpy(&_desc_str[1], tinyusb_string_descriptor[0], 2);
chr_count = 1;
} else {
// Convert ASCII string into UTF-16
if (index >= tinyusb_string_descriptor_len) {
return NULL;
}
const char *str = tinyusb_string_descriptor[index];
// Cap at max char
chr_count = strlen(str);
if (chr_count > 126) {
chr_count = 126;
}
for (uint8_t i = 0; i < chr_count; i++) {
_desc_str[1 + i] = str[i];
}
}
// first byte is len, second byte is string type
_desc_str[0] = (TUSB_DESC_STRING << 8 ) | (2*chr_count + 2);
return _desc_str;
}
/**
* @brief Invoked when received GET BOS DESCRIPTOR request.
*/
uint8_t const * tud_descriptor_bos_cb(void)
{
//log_d("");
return tinyusb_bos_descriptor;
}
__attribute__ ((weak)) bool tinyusb_vendor_control_request_cb(uint8_t rhport, tusb_control_request_t const * request){ return false; }
__attribute__ ((weak)) bool tinyusb_vendor_control_complete_cb(uint8_t rhport, tusb_control_request_t const * request){ return true; }
/**
* @brief Handle WebUSB and Vendor requests.
*/
bool tud_vendor_control_request_cb(uint8_t rhport, tusb_control_request_t const * request)
{
if(WEBUSB_ENABLED && (request->bRequest == VENDOR_REQUEST_WEBUSB
|| (request->bRequest == VENDOR_REQUEST_MICROSOFT && request->wIndex == 7))){
if(request->bRequest == VENDOR_REQUEST_WEBUSB){
// match vendor request in BOS descriptor
// Get landing page url
tinyusb_url_descriptor.bLength = 3 + strlen(WEBUSB_URL);
snprintf(tinyusb_url_descriptor.url, 127, "%s", WEBUSB_URL);
return tud_control_xfer(rhport, request, (void*) &tinyusb_url_descriptor, tinyusb_url_descriptor.bLength);
}
// Get Microsoft OS 2.0 compatible descriptor
uint16_t total_len;
memcpy(&total_len, tinyusb_ms_os_20_descriptor + 8, 2);
return tud_control_xfer(rhport, request, (void*) tinyusb_ms_os_20_descriptor, total_len);
}
return tinyusb_vendor_control_request_cb(rhport, request);
}
bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_request_t const * request)
{
if(!WEBUSB_ENABLED || !(request->bRequest == VENDOR_REQUEST_WEBUSB
|| (request->bRequest == VENDOR_REQUEST_MICROSOFT && request->wIndex == 7))){
return tinyusb_vendor_control_complete_cb(rhport, request);
}
return true;
}
/*
* Required Callbacks
* */
#if CFG_TUD_HID
__attribute__ ((weak)) const uint8_t * tud_hid_descriptor_report_cb(void){return NULL;}
__attribute__ ((weak)) uint16_t tud_hid_get_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen){return 0;}
__attribute__ ((weak)) void tud_hid_set_report_cb(uint8_t report_id, hid_report_type_t report_type, const uint8_t * buffer, uint16_t bufsize){}
#endif
#if CFG_TUD_MSC
__attribute__ ((weak)) bool tud_msc_test_unit_ready_cb(uint8_t lun){return false;}
__attribute__ ((weak)) void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4]){}
__attribute__ ((weak)) void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_size){}
__attribute__ ((weak)) int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize){return -1;}
__attribute__ ((weak)) int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize){return -1;}
__attribute__ ((weak)) int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, uint16_t bufsize){return -1;}
#endif
/*
* Private API
* */
static bool usb_persist_enabled = false;
static restart_type_t usb_persist_mode = RESTART_NO_PERSIST;
static bool tinyusb_reserve_in_endpoint(uint8_t endpoint){
if(endpoint > 6 || (tinyusb_endpoints.in & BIT(endpoint)) != 0){
return false;
}
tinyusb_endpoints.in |= BIT(endpoint);
return true;
}
static bool tinyusb_reserve_out_endpoint(uint8_t endpoint){
if(endpoint > 6 || (tinyusb_endpoints.out & BIT(endpoint)) != 0){
return false;
}
tinyusb_endpoints.out |= BIT(endpoint);
return true;
}
static bool tinyusb_has_available_fifos(void){
uint8_t max_endpoints = 4, active_endpoints = 0;
if (tinyusb_loaded_interfaces_mask & BIT(USB_INTERFACE_CDC)) {
max_endpoints = 5; //CDC endpoint 0x85 is actually not linked to FIFO and not used
}
for(uint8_t i=1; i<7; i++){
if((tinyusb_endpoints.in & BIT(i)) != 0){
active_endpoints++;
}
}
return active_endpoints < max_endpoints;
}
static uint16_t tinyusb_load_descriptor(tinyusb_interface_t interface, uint8_t * dst, uint8_t * itf)
{
if(tinyusb_loaded_interfaces_callbacks[interface]){
return tinyusb_loaded_interfaces_callbacks[interface](dst, itf);
}
return 0;
}
static bool tinyusb_load_enabled_interfaces(){
tinyusb_config_descriptor_len += TUD_CONFIG_DESC_LEN;
tinyusb_config_descriptor = (uint8_t *)malloc(tinyusb_config_descriptor_len);
if (tinyusb_config_descriptor == NULL) {
log_e("Descriptor Malloc Failed");
return false;
}
uint8_t * dst = tinyusb_config_descriptor + TUD_CONFIG_DESC_LEN;
for(int i=0; i<USB_INTERFACE_MAX; i++){
if (tinyusb_loaded_interfaces_mask & (1U << i)) {
uint16_t len = tinyusb_load_descriptor((tinyusb_interface_t)i, dst, &tinyusb_loaded_interfaces_num);
if (!len) {
log_e("Descriptor Load Failed");
return false;
} else {
if(i == USB_INTERFACE_CDC){
if(!tinyusb_reserve_out_endpoint(3) ||!tinyusb_reserve_in_endpoint(4) || !tinyusb_reserve_in_endpoint(5)){
log_e("CDC Reserve Endpoints Failed");
return false;
}
}
dst += len;
}
}
}
uint8_t str_index = tinyusb_add_string_descriptor("TinyUSB Device");
uint8_t descriptor[TUD_CONFIG_DESC_LEN] = {
//num configs, interface count, string index, total length, attribute, power in mA
TUD_CONFIG_DESCRIPTOR(1, tinyusb_loaded_interfaces_num, str_index, tinyusb_config_descriptor_len, USB_DEVICE_ATTRIBUTES, USB_DEVICE_POWER)
};
memcpy(tinyusb_config_descriptor, descriptor, TUD_CONFIG_DESC_LEN);
if ((tinyusb_loaded_interfaces_mask == (BIT(USB_INTERFACE_CDC) | BIT(USB_INTERFACE_DFU))) || (tinyusb_loaded_interfaces_mask == BIT(USB_INTERFACE_CDC))) {
usb_persist_enabled = true;
log_d("USB Persist enabled");
}
log_d("Load Done: if_num: %u, descr_len: %u, if_mask: 0x%x", tinyusb_loaded_interfaces_num, tinyusb_config_descriptor_len, tinyusb_loaded_interfaces_mask);
return true;
}
static inline char nibble_to_hex_char(uint8_t b)
{
if (b < 0xa) {
return '0' + b;
} else {
return 'a' + b - 0xa;
}
}
static void set_usb_serial_num(void)
{
/* Get the MAC address */
const uint32_t mac0 = REG_GET_FIELD(EFUSE_RD_MAC_SPI_SYS_0_REG, EFUSE_MAC_0);
const uint32_t mac1 = REG_GET_FIELD(EFUSE_RD_MAC_SPI_SYS_1_REG, EFUSE_MAC_1);
uint8_t mac_bytes[6];
memcpy(mac_bytes, &mac0, 4);
memcpy(mac_bytes + 4, &mac1, 2);
/* Convert to UTF16 string */
uint8_t* srl = (uint8_t*)USB_DEVICE_SERIAL;
for (int i = 0; i < 6; ++i) {
uint8_t b = mac_bytes[5 - i]; /* printing from the MSB */
if (i) {
*srl++ = ':';
}
*srl++ = nibble_to_hex_char(b >> 4);
*srl++ = nibble_to_hex_char(b & 0xf);
}
*srl++ = '\0';
}
static void tinyusb_apply_device_config(tinyusb_device_config_t *config){
if(config->product_name){
snprintf(USB_DEVICE_PRODUCT, 126, "%s", config->product_name);
}
if(config->manufacturer_name){
snprintf(USB_DEVICE_MANUFACTURER, 126, "%s", config->manufacturer_name);
}
if(config->serial_number && config->serial_number[0]){
snprintf(USB_DEVICE_SERIAL, 126, "%s", config->serial_number);
} else {
set_usb_serial_num();
}
if(config->webusb_url){
snprintf(WEBUSB_URL, 126, "%s", config->webusb_url);
}
WEBUSB_ENABLED = config->webusb_enabled;
USB_DEVICE_ATTRIBUTES = config->usb_attributes;
USB_DEVICE_POWER = config->usb_power_ma;
tinyusb_device_descriptor.bcdUSB = config->usb_version;
tinyusb_device_descriptor.idVendor = config->vid;
tinyusb_device_descriptor.idProduct = config->pid;
tinyusb_device_descriptor.bcdDevice = config->fw_version;
tinyusb_device_descriptor.bDeviceClass = config->usb_class;
tinyusb_device_descriptor.bDeviceSubClass = config->usb_subclass;
tinyusb_device_descriptor.bDeviceProtocol = config->usb_protocol;
}
static void IRAM_ATTR usb_persist_shutdown_handler(void)
{
if(usb_persist_mode != RESTART_NO_PERSIST){
if (usb_persist_enabled) {
usb_dc_prepare_persist();
}
if (usb_persist_mode == RESTART_BOOTLOADER) {
//USB CDC Download
if (usb_persist_enabled) {
chip_usb_set_persist_flags(USBDC_PERSIST_ENA);
}
REG_WRITE(RTC_CNTL_OPTION1_REG, RTC_CNTL_FORCE_DOWNLOAD_BOOT);
} else if (usb_persist_mode == RESTART_BOOTLOADER_DFU) {
//DFU Download
chip_usb_set_persist_flags(USBDC_BOOT_DFU);
REG_WRITE(RTC_CNTL_OPTION1_REG, RTC_CNTL_FORCE_DOWNLOAD_BOOT);
} else if (usb_persist_enabled) {
//USB Persist reboot
chip_usb_set_persist_flags(USBDC_PERSIST_ENA);
}
}
}
// USB Device Driver task
// This top level thread processes all usb events and invokes callbacks
static void usb_device_task(void *param) {
(void)param;
while(1) tud_task(); // RTOS forever loop
}
/*
* PUBLIC API
* */
esp_err_t tinyusb_enable_interface(tinyusb_interface_t interface, uint16_t descriptor_len, tinyusb_descriptor_cb_t cb)
{
if((interface >= USB_INTERFACE_MAX) || (tinyusb_loaded_interfaces_mask & (1U << interface))){
log_e("Interface %u not enabled", interface);
return ESP_FAIL;
}
tinyusb_loaded_interfaces_mask |= (1U << interface);
tinyusb_config_descriptor_len += descriptor_len;
tinyusb_loaded_interfaces_callbacks[interface] = cb;
log_d("Interface %u enabled", interface);
return ESP_OK;
}
esp_err_t tinyusb_init(tinyusb_device_config_t *config) {
static bool initialized = false;
if(initialized){
return ESP_OK;
}
initialized = true;
tinyusb_endpoints.val = 0;
tinyusb_apply_device_config(config);
if (!tinyusb_load_enabled_interfaces()) {
initialized = false;
return ESP_FAIL;
}
bool usb_did_persist = (USB_WRAP.date.val == USBDC_PERSIST_ENA);
if(usb_did_persist && usb_persist_enabled){
// Enable USB/IO_MUX peripheral reset, if coming from persistent reboot
REG_CLR_BIT(RTC_CNTL_USB_CONF_REG, RTC_CNTL_IO_MUX_RESET_DISABLE);
REG_CLR_BIT(RTC_CNTL_USB_CONF_REG, RTC_CNTL_USB_RESET_DISABLE);
} else {
// Reset USB module
periph_module_reset(PERIPH_USB_MODULE);
periph_module_enable(PERIPH_USB_MODULE);
}
if (esp_register_shutdown_handler(usb_persist_shutdown_handler) != ESP_OK) {
initialized = false;
return ESP_FAIL;
}
tinyusb_config_t tusb_cfg = {
.external_phy = false // In the most cases you need to use a `false` value
};
esp_err_t err = tinyusb_driver_install(&tusb_cfg);
if (err != ESP_OK) {
initialized = false;
return err;
}
xTaskCreate(usb_device_task, "usbd", 4096, NULL, configMAX_PRIORITIES - 1, NULL);
return err;
}
void usb_persist_restart(restart_type_t mode)
{
if (mode < RESTART_TYPE_MAX) {
usb_persist_mode = mode;
esp_restart();
}
}
uint8_t tinyusb_add_string_descriptor(const char * str){
if(str == NULL || tinyusb_string_descriptor_len >= MAX_STRING_DESCRIPTORS){
return 0;
}
uint8_t index = tinyusb_string_descriptor_len;
tinyusb_string_descriptor[tinyusb_string_descriptor_len++] = (char*)str;
return index;
}
uint8_t tinyusb_get_free_duplex_endpoint(void){
if(!tinyusb_has_available_fifos()){
log_e("No available IN endpoints");
return 0;
}
for(uint8_t i=1; i<7; i++){
if((tinyusb_endpoints.in & BIT(i)) == 0 && (tinyusb_endpoints.out & BIT(i)) == 0){
tinyusb_endpoints.in |= BIT(i);
tinyusb_endpoints.out |= BIT(i);
return i;
}
}
log_e("No available duplex endpoints");
return 0;
}
uint8_t tinyusb_get_free_in_endpoint(void){
if(!tinyusb_has_available_fifos()){
log_e("No available IN endpoints");
return 0;
}
for(uint8_t i=1; i<7; i++){
if((tinyusb_endpoints.in & BIT(i)) == 0 && (tinyusb_endpoints.out & BIT(i)) != 0){
tinyusb_endpoints.in |= BIT(i);
return i;
}
}
for(uint8_t i=1; i<7; i++){
if((tinyusb_endpoints.in & BIT(i)) == 0){
tinyusb_endpoints.in |= BIT(i);
return i;
}
}
return 0;
}
uint8_t tinyusb_get_free_out_endpoint(void){
for(uint8_t i=1; i<7; i++){
if((tinyusb_endpoints.out & BIT(i)) == 0 && (tinyusb_endpoints.in & BIT(i)) != 0){
tinyusb_endpoints.out |= BIT(i);
return i;
}
}
for(uint8_t i=1; i<7; i++){
if((tinyusb_endpoints.out & BIT(i)) == 0){
tinyusb_endpoints.out |= BIT(i);
return i;
}
}
return 0;
}
/*
void usb_dw_reg_dump(void)
{
#define USB_PRINT_REG(r) printf("USB0." #r " = 0x%x;\n", USB0.r)
#define USB_PRINT_IREG(i, r) printf("USB0.in_ep_reg[%u]." #r " = 0x%x;\n", i, USB0.in_ep_reg[i].r)
#define USB_PRINT_OREG(i, r) printf("USB0.out_ep_reg[%u]." #r " = 0x%x;\n", i, USB0.out_ep_reg[i].r)
uint8_t i;
USB_PRINT_REG(gotgctl);
USB_PRINT_REG(gotgint);
USB_PRINT_REG(gahbcfg);
USB_PRINT_REG(gusbcfg);
USB_PRINT_REG(grstctl);
USB_PRINT_REG(gintsts);
USB_PRINT_REG(gintmsk);
USB_PRINT_REG(grxstsr);
USB_PRINT_REG(grxstsp);
USB_PRINT_REG(grxfsiz);
USB_PRINT_REG(gnptxsts);
USB_PRINT_REG(gpvndctl);
USB_PRINT_REG(ggpio);
USB_PRINT_REG(guid);
USB_PRINT_REG(gsnpsid);
USB_PRINT_REG(ghwcfg1);
USB_PRINT_REG(ghwcfg2);
USB_PRINT_REG(ghwcfg3);
USB_PRINT_REG(ghwcfg4);
USB_PRINT_REG(glpmcfg);
USB_PRINT_REG(gpwrdn);
USB_PRINT_REG(gdfifocfg);
USB_PRINT_REG(gadpctl);
USB_PRINT_REG(hptxfsiz);
USB_PRINT_REG(hcfg);
USB_PRINT_REG(hfir);
USB_PRINT_REG(hfnum);
USB_PRINT_REG(hptxsts);
USB_PRINT_REG(haint);
USB_PRINT_REG(haintmsk);
USB_PRINT_REG(hflbaddr);
USB_PRINT_REG(hprt);
USB_PRINT_REG(dcfg);
USB_PRINT_REG(dctl);
USB_PRINT_REG(dsts);
USB_PRINT_REG(diepmsk);
USB_PRINT_REG(doepmsk);
USB_PRINT_REG(daint);
USB_PRINT_REG(daintmsk);
USB_PRINT_REG(dtknqr1);
USB_PRINT_REG(dtknqr2);
USB_PRINT_REG(dvbusdis);
USB_PRINT_REG(dvbuspulse);
USB_PRINT_REG(dtknqr3_dthrctl);
USB_PRINT_REG(dtknqr4_fifoemptymsk);
USB_PRINT_REG(deachint);
USB_PRINT_REG(deachintmsk);
USB_PRINT_REG(pcgctrl);
USB_PRINT_REG(pcgctrl1);
USB_PRINT_REG(gnptxfsiz);
for (i = 0; i < 4; i++) {
printf("USB0.dieptxf[%u] = 0x%x;\n", i, USB0.dieptxf[i]);
}
// for (i = 0; i < 16; i++) {
// printf("USB0.diepeachintmsk[%u] = 0x%x;\n", i, USB0.diepeachintmsk[i]);
// }
// for (i = 0; i < 16; i++) {
// printf("USB0.doepeachintmsk[%u] = 0x%x;\n", i, USB0.doepeachintmsk[i]);
// }
for (i = 0; i < 7; i++) {
printf("// EP %u:\n", i);
USB_PRINT_IREG(i, diepctl);
USB_PRINT_IREG(i, diepint);
USB_PRINT_IREG(i, dieptsiz);
USB_PRINT_IREG(i, diepdma);
USB_PRINT_IREG(i, dtxfsts);
USB_PRINT_OREG(i, doepctl);
USB_PRINT_OREG(i, doepint);
USB_PRINT_OREG(i, doeptsiz);
USB_PRINT_OREG(i, doepdma);
}
}
*/
#endif /* CONFIG_USB_ENABLED */

View File

@ -1,103 +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 "esp32-hal.h"
#if CONFIG_IDF_TARGET_ESP32S2
#if CONFIG_USB_ENABLED
#ifdef __cplusplus
extern "C" {
#endif
#include "tinyusb.h"
typedef struct {
uint16_t vid;
uint16_t pid;
const char * product_name;
const char * manufacturer_name;
const char * serial_number;
uint16_t fw_version;
uint16_t usb_version;
uint8_t usb_class;
uint8_t usb_subclass;
uint8_t usb_protocol;
uint8_t usb_attributes;
uint16_t usb_power_ma;
bool webusb_enabled;
const char * webusb_url;
} tinyusb_device_config_t;
#define TINYUSB_CONFIG_DEFAULT() { \
.vid = USB_ESPRESSIF_VID, \
.pid = 0x0002, \
.product_name = CONFIG_USB_DESC_PRODUCT_STRING, \
.manufacturer_name = CONFIG_USB_DESC_MANUFACTURER_STRING, \
.serial_number = CONFIG_USB_DESC_SERIAL_STRING, \
.fw_version = CONFIG_USB_DESC_BCDDEVICE, \
.usb_version = 0x0200, \
.usb_class = TUSB_CLASS_MISC, \
.usb_subclass = MISC_SUBCLASS_COMMON, \
.usb_protocol = MISC_PROTOCOL_IAD, \
.usb_attributes = TUSB_DESC_CONFIG_ATT_SELF_POWERED, \
.usb_power_ma = 500, \
.webusb_enabled = false, \
.webusb_url = "espressif.github.io/arduino-esp32/webusb.html" \
}
esp_err_t tinyusb_init(tinyusb_device_config_t *config);
/*
* USB Persistence API
* */
typedef enum {
RESTART_NO_PERSIST,
RESTART_PERSIST,
RESTART_BOOTLOADER,
RESTART_BOOTLOADER_DFU,
RESTART_TYPE_MAX
} restart_type_t;
void usb_persist_restart(restart_type_t mode);
// The following definitions and functions are to be used only by the drivers
typedef enum {
USB_INTERFACE_CDC,
USB_INTERFACE_DFU,
USB_INTERFACE_HID,
USB_INTERFACE_VENDOR,
USB_INTERFACE_MSC,
USB_INTERFACE_MIDI,
USB_INTERFACE_CUSTOM,
USB_INTERFACE_MAX
} tinyusb_interface_t;
typedef uint16_t (*tinyusb_descriptor_cb_t)(uint8_t * dst, uint8_t * itf);
esp_err_t tinyusb_enable_interface(tinyusb_interface_t interface, uint16_t descriptor_len, tinyusb_descriptor_cb_t cb);
uint8_t tinyusb_add_string_descriptor(const char * str);
uint8_t tinyusb_get_free_duplex_endpoint(void);
uint8_t tinyusb_get_free_in_endpoint(void);
uint8_t tinyusb_get_free_out_endpoint(void);
#ifdef __cplusplus
}
#endif
#endif /* CONFIG_USB_ENABLED */
#endif /* CONFIG_IDF_TARGET_ESP32S2 */

View File

@ -1,229 +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.h"
#include "esp32-hal-touch.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_attr.h"
#include "soc/rtc_io_reg.h"
#include "soc/rtc_cntl_reg.h"
#include "soc/sens_reg.h"
#include "soc/sens_struct.h"
#include "driver/touch_sensor.h"
#include "esp_system.h"
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
#include "esp32/rom/ets_sys.h"
#include "esp_intr_alloc.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/rom/ets_sys.h"
#include "esp_intr_alloc.h"
#include "soc/periph_defs.h"
#else
#error Target CONFIG_IDF_TARGET is not supported
#endif
#else // ESP32 Before IDF 4.0
#include "rom/ets_sys.h"
#include "esp_intr.h"
#endif
#include "esp32-hal-gpio.h"
static uint16_t __touchSleepCycles = 0x1000;
static uint16_t __touchMeasureCycles = 0x1000;
typedef void (*voidFuncPtr)(void);
static voidFuncPtr __touchInterruptHandlers[10] = {0,};
static intr_handle_t touch_intr_handle = NULL;
void ARDUINO_ISR_ATTR __touchISR(void * arg)
{
#if CONFIG_IDF_TARGET_ESP32
uint32_t pad_intr = READ_PERI_REG(SENS_SAR_TOUCH_CTRL2_REG) & 0x3ff;
uint32_t rtc_intr = READ_PERI_REG(RTC_CNTL_INT_ST_REG);
uint8_t i = 0;
//clear interrupt
WRITE_PERI_REG(RTC_CNTL_INT_CLR_REG, rtc_intr);
SET_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL2_REG, SENS_TOUCH_MEAS_EN_CLR);
if (rtc_intr & RTC_CNTL_TOUCH_INT_ST) {
for (i = 0; i < 10; ++i) {
if ((pad_intr >> i) & 0x01) {
if(__touchInterruptHandlers[i]){
__touchInterruptHandlers[i]();
}
}
}
}
#endif
}
void __touchSetCycles(uint16_t measure, uint16_t sleep)
{
__touchSleepCycles = sleep;
__touchMeasureCycles = measure;
#if CONFIG_IDF_TARGET_ESP32
//Touch pad SleepCycle Time
SET_PERI_REG_BITS(SENS_SAR_TOUCH_CTRL2_REG, SENS_TOUCH_SLEEP_CYCLES, __touchSleepCycles, SENS_TOUCH_SLEEP_CYCLES_S);
//Touch Pad Measure Time
SET_PERI_REG_BITS(SENS_SAR_TOUCH_CTRL1_REG, SENS_TOUCH_MEAS_DELAY, __touchMeasureCycles, SENS_TOUCH_MEAS_DELAY_S);
#else
touch_pad_set_meas_time(sleep, measure);
#endif
}
void __touchInit()
{
static bool initialized = false;
if(initialized){
return;
}
initialized = true;
#if CONFIG_IDF_TARGET_ESP32
SET_PERI_REG_BITS(RTC_IO_TOUCH_CFG_REG, RTC_IO_TOUCH_XPD_BIAS, 1, RTC_IO_TOUCH_XPD_BIAS_S);
SET_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL2_REG, SENS_TOUCH_MEAS_EN_CLR);
//clear touch enable
WRITE_PERI_REG(SENS_SAR_TOUCH_ENABLE_REG, 0x0);
__touchSetCycles(__touchMeasureCycles, __touchSleepCycles);
esp_intr_alloc(ETS_RTC_CORE_INTR_SOURCE, (int)ARDUINO_ISR_FLAG, __touchISR, NULL, &touch_intr_handle);
#else
touch_pad_init();
touch_pad_set_voltage(TOUCH_HVOLT_2V7, TOUCH_LVOLT_0V5, TOUCH_HVOLT_ATTEN_0V5);
touch_pad_set_idle_channel_connect(TOUCH_PAD_CONN_GND);
__touchSetCycles(__touchMeasureCycles, __touchSleepCycles);
touch_pad_denoise_t denoise = {
.grade = TOUCH_PAD_DENOISE_BIT4,
.cap_level = TOUCH_PAD_DENOISE_CAP_L4,
};
touch_pad_denoise_set_config(&denoise);
touch_pad_denoise_enable();
touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER);
touch_pad_fsm_start();
#endif
}
uint16_t __touchRead(uint8_t pin)
{
int8_t pad = digitalPinToTouchChannel(pin);
if(pad < 0){
return 0;
}
pinMode(pin, ANALOG);
__touchInit();
#if CONFIG_IDF_TARGET_ESP32
uint32_t v0 = READ_PERI_REG(SENS_SAR_TOUCH_ENABLE_REG);
//Disable Intr & enable touch pad
WRITE_PERI_REG(SENS_SAR_TOUCH_ENABLE_REG,
(v0 & ~((1 << (pad + SENS_TOUCH_PAD_OUTEN2_S)) | (1 << (pad + SENS_TOUCH_PAD_OUTEN1_S))))
| (1 << (pad + SENS_TOUCH_PAD_WORKEN_S)));
SET_PERI_REG_MASK(SENS_SAR_TOUCH_ENABLE_REG, (1 << (pad + SENS_TOUCH_PAD_WORKEN_S)));
uint32_t rtc_tio_reg = RTC_IO_TOUCH_PAD0_REG + pad * 4;
WRITE_PERI_REG(rtc_tio_reg, (READ_PERI_REG(rtc_tio_reg)
& ~(RTC_IO_TOUCH_PAD0_DAC_M))
| (7 << RTC_IO_TOUCH_PAD0_DAC_S)//Touch Set Slope
| RTC_IO_TOUCH_PAD0_TIE_OPT_M //Enable Tie,Init Level
| RTC_IO_TOUCH_PAD0_START_M //Enable Touch Pad IO
| RTC_IO_TOUCH_PAD0_XPD_M); //Enable Touch Pad Power on
//force oneTime test start
SET_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL2_REG, SENS_TOUCH_START_EN_M|SENS_TOUCH_START_FORCE_M);
SET_PERI_REG_BITS(SENS_SAR_TOUCH_CTRL1_REG, SENS_TOUCH_XPD_WAIT, 10, SENS_TOUCH_XPD_WAIT_S);
while (GET_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL2_REG, SENS_TOUCH_MEAS_DONE) == 0) {};
uint16_t touch_value = READ_PERI_REG(SENS_SAR_TOUCH_OUT1_REG + (pad / 2) * 4) >> ((pad & 1) ? SENS_TOUCH_MEAS_OUT1_S : SENS_TOUCH_MEAS_OUT0_S);
//clear touch force ,select the Touch mode is Timer
CLEAR_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL2_REG, SENS_TOUCH_START_EN_M|SENS_TOUCH_START_FORCE_M);
//restore previous value
WRITE_PERI_REG(SENS_SAR_TOUCH_ENABLE_REG, v0);
return touch_value;
#else
static uint32_t chan_mask = 0;
uint32_t value = 0;
if((chan_mask & (1 << pad)) == 0){
if(touch_pad_set_thresh((touch_pad_t)pad, TOUCH_PAD_THRESHOLD_MAX) != ESP_OK){
log_e("touch_pad_set_thresh failed");
} else if(touch_pad_config((touch_pad_t)pad) != ESP_OK){
log_e("touch_pad_config failed");
} else {
chan_mask |= (1 << pad);
}
}
if((chan_mask & (1 << pad)) != 0) {
if(touch_pad_read_raw_data((touch_pad_t)pad, &value) != ESP_OK){
log_e("touch_pad_read_raw_data failed");
}
}
return value;
#endif
}
void __touchAttachInterrupt(uint8_t pin, void (*userFunc)(void), uint16_t threshold)
{
int8_t pad = digitalPinToTouchChannel(pin);
if(pad < 0){
return;
}
pinMode(pin, ANALOG);
__touchInit();
__touchInterruptHandlers[pad] = userFunc;
#if CONFIG_IDF_TARGET_ESP32
//clear touch force ,select the Touch mode is Timer
CLEAR_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL2_REG, SENS_TOUCH_START_EN_M|SENS_TOUCH_START_FORCE_M);
//interrupt when touch value < threshold
CLEAR_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL1_REG, SENS_TOUCH_OUT_SEL);
//Intr will give ,when SET0 < threshold
SET_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL1_REG, SENS_TOUCH_OUT_1EN);
//Enable Rtc Touch Module Intr,the Interrupt need Rtc out Enable
SET_PERI_REG_MASK(RTC_CNTL_INT_ENA_REG, RTC_CNTL_TOUCH_INT_ENA);
//set threshold
uint8_t shift = (pad & 1) ? SENS_TOUCH_OUT_TH1_S : SENS_TOUCH_OUT_TH0_S;
SET_PERI_REG_BITS((SENS_SAR_TOUCH_THRES1_REG + (pad / 2) * 4), SENS_TOUCH_OUT_TH0, threshold, shift);
uint32_t rtc_tio_reg = RTC_IO_TOUCH_PAD0_REG + pad * 4;
WRITE_PERI_REG(rtc_tio_reg, (READ_PERI_REG(rtc_tio_reg)
& ~(RTC_IO_TOUCH_PAD0_DAC_M))
| (7 << RTC_IO_TOUCH_PAD0_DAC_S)//Touch Set Slope
| RTC_IO_TOUCH_PAD0_TIE_OPT_M //Enable Tie,Init Level
| RTC_IO_TOUCH_PAD0_START_M //Enable Touch Pad IO
| RTC_IO_TOUCH_PAD0_XPD_M); //Enable Touch Pad Power on
//Enable Digital rtc control :work mode and out mode
SET_PERI_REG_MASK(SENS_SAR_TOUCH_ENABLE_REG,
(1 << (pad + SENS_TOUCH_PAD_WORKEN_S)) | \
(1 << (pad + SENS_TOUCH_PAD_OUTEN2_S)) | \
(1 << (pad + SENS_TOUCH_PAD_OUTEN1_S)));
#else
#endif
}
extern uint16_t touchRead(uint8_t pin) __attribute__ ((weak, alias("__touchRead")));
extern void touchAttachInterrupt(uint8_t pin, void (*userFunc)(void), uint16_t threshold) __attribute__ ((weak, alias("__touchAttachInterrupt")));
extern void touchSetCycles(uint16_t measure, uint16_t sleep) __attribute__ ((weak, alias("__touchSetCycles")));

View File

@ -1,56 +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_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
/*
* 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 (values close to 0 mean touch detected)
* You can use this method to chose a good threshold value
* to use as value for touchAttachInterrupt
* */
uint16_t touchRead(uint8_t pin);
/*
* Set function to be called if touch pad value falls
* below the given threshold. Use touchRead to determine
* a proper threshold between touched and untouched state
* */
void touchAttachInterrupt(uint8_t pin, void (*userFunc)(void), uint16_t threshold);
#ifdef __cplusplus
}
#endif
#endif /* MAIN_ESP32_HAL_TOUCH_H_ */

View File

@ -1,161 +0,0 @@
/*
core_esp8266_noniso.c - nonstandard (but usefull) conversion functions
Copyright (c) 2014 Ivan Grokhotkov. 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
Modified 03 April 2015 by Markus Sattler
*/
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <stdint.h>
#include <math.h>
#include "stdlib_noniso.h"
void reverse(char* begin, char* end) {
char *is = begin;
char *ie = end - 1;
while(is < ie) {
char tmp = *ie;
*ie = *is;
*is = tmp;
++is;
--ie;
}
}
char* ltoa(long value, char* result, int base) {
if(base < 2 || base > 16) {
*result = 0;
return result;
}
char* out = result;
long quotient = abs(value);
do {
const long tmp = quotient / base;
*out = "0123456789abcdef"[quotient - (tmp * base)];
++out;
quotient = tmp;
} while(quotient);
// Apply negative sign
if(value < 0)
*out++ = '-';
reverse(result, out);
*out = 0;
return result;
}
char* ultoa(unsigned long value, char* result, int base) {
if(base < 2 || base > 16) {
*result = 0;
return result;
}
char* out = result;
unsigned long quotient = value;
do {
const unsigned long tmp = quotient / base;
*out = "0123456789abcdef"[quotient - (tmp * base)];
++out;
quotient = tmp;
} while(quotient);
reverse(result, out);
*out = 0;
return result;
}
char * dtostrf(double number, signed char width, unsigned char prec, char *s) {
bool negative = false;
if (isnan(number)) {
strcpy(s, "nan");
return s;
}
if (isinf(number)) {
strcpy(s, "inf");
return s;
}
char* out = s;
int fillme = width; // how many cells to fill for the integer part
if (prec > 0) {
fillme -= (prec+1);
}
// Handle negative numbers
if (number < 0.0) {
negative = true;
fillme--;
number = -number;
}
// Round correctly so that print(1.999, 2) prints as "2.00"
// I optimized out most of the divisions
double rounding = 2.0;
for (uint8_t i = 0; i < prec; ++i)
rounding *= 10.0;
rounding = 1.0 / rounding;
number += rounding;
// Figure out how big our number really is
double tenpow = 1.0;
int digitcount = 1;
while (number >= 10.0 * tenpow) {
tenpow *= 10.0;
digitcount++;
}
number /= tenpow;
fillme -= digitcount;
// Pad unused cells with spaces
while (fillme-- > 0) {
*out++ = ' ';
}
// Handle negative sign
if (negative) *out++ = '-';
// Print the digits, and if necessary, the decimal point
digitcount += prec;
int8_t digit = 0;
while (digitcount-- > 0) {
digit = (int8_t)number;
if (digit > 9) digit = 9; // insurance
*out++ = (char)('0' | digit);
if ((digitcount == prec) && (prec > 0)) {
*out++ = '.';
}
number -= digit;
number *= 10.0;
}
// make sure the string is terminated
*out = 0;
return s;
}

View File

@ -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

View File

@ -1,50 +0,0 @@
/*
pulse.c - wiring pulseIn implementation 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 <limits.h>
#include "wiring_private.h"
#include "pins_arduino.h"
extern uint32_t xthal_get_ccount();
#define WAIT_FOR_PIN_STATE(state) \
while (digitalRead(pin) != (state)) { \
if (xthal_get_ccount() - start_cycle_count > timeout_cycles) { \
return 0; \
} \
}
// max timeout is 27 seconds at 160MHz clock and 54 seconds at 80MHz clock
//unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout)
//{
// const uint32_t max_timeout_us = clockCyclesToMicroseconds(UINT_MAX);
// if (timeout > max_timeout_us) {
// timeout = max_timeout_us;
// }
// const uint32_t timeout_cycles = microsecondsToClockCycles(timeout);
// const uint32_t start_cycle_count = xthal_get_ccount();
// WAIT_FOR_PIN_STATE(!state);
// WAIT_FOR_PIN_STATE(state);
// const uint32_t pulse_start_cycle_count = xthal_get_ccount();
// WAIT_FOR_PIN_STATE(!state);
// return clockCyclesToMicroseconds(xthal_get_ccount() - pulse_start_cycle_count);
//}
//unsigned long pulseInLong(uint8_t pin, uint8_t state, unsigned long timeout)
//{
// return pulseIn(pin, state, timeout);
//}

View File

@ -1,53 +0,0 @@
/*
wiring_shift.c - shiftOut() function
Part of Arduino - http://www.arduino.cc/
Copyright (c) 2005-2006 David A. Mellis
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., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
$Id: wiring.c 248 2007-02-03 15:36:30Z mellis $
*/
#include "wiring_shift.h"
#include "esp32-hal.h"
#include "wiring_private.h"
#include "esp32-hal-gpio.h"
uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder) {
uint8_t value = 0;
uint8_t i;
for(i = 0; i < 8; ++i) {
//digitalWrite(clockPin, HIGH);
if(bitOrder == LSBFIRST)
value |= digitalRead(dataPin) << i;
else
value |= digitalRead(dataPin) << (7 - i);
digitalWrite(clockPin, HIGH);
digitalWrite(clockPin, LOW);
}
return value;
}
void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val) {
uint8_t i;
for(i = 0; i < 8; i++) {
if(bitOrder == LSBFIRST)
digitalWrite(dataPin, !!(val & (1 << i)));
else
digitalWrite(dataPin, !!(val & (1 << (7 - i))));
digitalWrite(clockPin, HIGH);
digitalWrite(clockPin, LOW);
}
}

View File

@ -1,9 +0,0 @@
#pragma once
#define LSBFIRST 0
#define MSBFIRST 1
#include <stdint.h>
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);

View File

@ -30,7 +30,8 @@ extern "C" {
#include <esp_log.h>
#include <utility>
#include <fmt/core.h>
#include "goefmt.h"
#include "esp32-hal-i2c.h"
#include "esp32-hal-log.h"
@ -52,7 +53,7 @@ std::string toString(i2c_err_t val)
case I2C_ERROR_NO_BEGIN: return "I2C_ERROR_NO_BEGIN";
default:
ESP_LOGW("WIRE", "unknown i2c_err_t(%i)", std::to_underlying(val));
return fmt::format("Unknown i2c_err_t({})", std::to_underlying(val));
return goe::format("Unknown i2c_err_t({})", std::to_underlying(val));
}
}
@ -224,7 +225,7 @@ uint8_t TwoWire::requestFrom(uint16_t address, uint8_t size, bool sendStop)
if(cnt < (I2C_BUFFER_LENGTH-1) && (size + cnt) <= I2C_BUFFER_LENGTH) { // any room left in rxBuffer
rxQueued += size;
} else { // no room to receive more!
log_e("rxBuff overflow %d", cnt + size);
log_e("rxBuff overflow %lu", cnt + size);
cnt = 0;
last_error = I2C_ERROR_MEMORY;
flush();