mirror of
https://github.com/m5stack/M5Stack_MicroPython.git
synced 2026-05-20 10:14:44 -07:00
Updated SPI module, bugs fixed
Refactored PWM module Prebuilt firmwares available as one zip file
This commit is contained in:
@@ -25,3 +25,9 @@ patches/
|
||||
sdkconfig
|
||||
sdkconfig.old
|
||||
_sdkconfig.saved
|
||||
sdkconfig.fw_esp32
|
||||
sdkconfig.fw_esp32_ota
|
||||
sdkconfig.fw_psram
|
||||
sdkconfig.fw_psram_ota
|
||||
|
||||
makefirmwares.sh
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
|
||||
|
||||
#=======================
|
||||
TOOLS_VER=ver20180103.id
|
||||
TOOLS_VER=ver20180107.id
|
||||
#=======================
|
||||
|
||||
# -----------------------------
|
||||
|
||||
@@ -80,34 +80,43 @@ extern uint8_t disp_used_spi_host;
|
||||
int checkSPIBUS(int8_t bus, int8_t mosi, uint8_t miso, uint8_t sck)
|
||||
{
|
||||
if ((disp_used_spi_host > 0) && (MPy_SPIbus[disp_used_spi_host]->mosi_io_num >= 0)) return -3; // bus used by display driver
|
||||
if (MPy_SPIbus[bus] == NULL) return -2; // bus not available
|
||||
if (MPy_SPIbus[bus]->mosi_io_num < 0) return 1; // bus not configured, free to use
|
||||
|
||||
if (MPy_SPIbus[bus] == NULL) return -2; // bus not available
|
||||
if (MPy_SPIbus[bus]->mosi_io_num < 0) return 1; // bus not configured, free to use
|
||||
|
||||
if ((mosi != MPy_SPIbus[bus]->mosi_io_num) ||
|
||||
(miso != MPy_SPIbus[bus]->miso_io_num) ||
|
||||
(sck != MPy_SPIbus[bus]->sclk_io_num)) return -1; // requested pins different than configured
|
||||
return 0; // bus already configured with the same pins
|
||||
(sck != MPy_SPIbus[bus]->sclk_io_num)) return -1; // requested pins different than configured
|
||||
return 0; // bus already configured with the same pins
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
STATIC void machine_hw_spi_deinit_internal(machine_hw_spi_obj_t *self)
|
||||
//---------------------------------------------------------------------------------
|
||||
STATIC void machine_hw_spi_deinit_internal(machine_hw_spi_obj_t *self, int freebus)
|
||||
{
|
||||
spi_device_handle_t handle = self->spi.handle;
|
||||
if (spi_bus_remove_device(handle) != ESP_OK) {
|
||||
mp_raise_msg(&mp_type_OSError, "error at deinitialization");
|
||||
mp_raise_msg(&mp_type_OSError, "error removing spi device");
|
||||
}
|
||||
spi_host_t *host=(spi_host_t*)handle->host;
|
||||
int i;
|
||||
for (i=0; i<NO_CS; i++) {
|
||||
if (host->device[i] != NULL) break;
|
||||
}
|
||||
if (freebus) {
|
||||
// Check if spi buss can be freed
|
||||
spi_host_t *host=(spi_host_t*)handle->host;
|
||||
int i;
|
||||
for (i=0; i<NO_CS; i++) {
|
||||
if (host->device[i] != NULL) break;
|
||||
}
|
||||
|
||||
if (i == NO_CS) {
|
||||
// no more devices attached to host, free bus
|
||||
spi_bus_free(self->host);
|
||||
MPy_SPIbus[self->host]->sclk_io_num = -1;
|
||||
MPy_SPIbus[self->host]->mosi_io_num = -1;
|
||||
MPy_SPIbus[self->host]->miso_io_num = -1;
|
||||
if (i == NO_CS) {
|
||||
// no more devices attached to host, free bus
|
||||
if (spi_bus_free(self->host) != ESP_OK) {
|
||||
mp_raise_msg(&mp_type_OSError, "error freeing spi host");
|
||||
}
|
||||
gpio_pad_select_gpio(MPy_SPIbus[self->host]->miso_io_num);
|
||||
gpio_pad_select_gpio(MPy_SPIbus[self->host]->mosi_io_num);
|
||||
gpio_pad_select_gpio(MPy_SPIbus[self->host]->sclk_io_num);
|
||||
MPy_SPIbus[self->host]->sclk_io_num = -1;
|
||||
MPy_SPIbus[self->host]->mosi_io_num = -1;
|
||||
MPy_SPIbus[self->host]->miso_io_num = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,22 +132,38 @@ STATIC void machine_hw_spi_init_internal(
|
||||
int8_t mosi,
|
||||
int8_t miso,
|
||||
int8_t cs,
|
||||
int8_t duplex) {
|
||||
int8_t duplex,
|
||||
uint8_t new) {
|
||||
|
||||
// if we're not initialized, then we're implicitly 'changed', since this is the init routine
|
||||
uint16_t changed = self->state != MACHINE_HW_SPI_STATE_INIT;
|
||||
|
||||
esp_err_t ret;
|
||||
int bus_state = 0;
|
||||
machine_hw_spi_obj_t old_self = *self;
|
||||
machine_hw_spi_obj_t old_self;
|
||||
machine_hw_spi_obj_t *pold_self;
|
||||
|
||||
if ((host > -1) && (host != self->host)) {
|
||||
if (new) pold_self = self;
|
||||
else {
|
||||
memcpy(&old_self, self, sizeof(machine_hw_spi_obj_t));
|
||||
pold_self = &old_self;
|
||||
}
|
||||
|
||||
if (((mosi < 0) && (MPy_SPIbus[self->host]->mosi_io_num <0)) ||
|
||||
((miso < 0) && (MPy_SPIbus[self->host]->miso_io_num <0)) ||
|
||||
((sck < 0) && (MPy_SPIbus[self->host]->sclk_io_num <0))) {
|
||||
mp_raise_ValueError("Error, not all spi pins given");
|
||||
}
|
||||
|
||||
uint16_t changed = pold_self->state != MACHINE_HW_SPI_STATE_INIT;
|
||||
|
||||
if (host > -1) {
|
||||
// Host initialization or host change
|
||||
#if CONFIG_SPIRAM_SPEED_80M
|
||||
if (host != HSPI_HOST) {
|
||||
mp_raise_ValueError("SPI host must be HSPI(1)");
|
||||
}
|
||||
#else
|
||||
if (host != HSPI_HOST && host != VSPI_HOST) {
|
||||
if ((host != HSPI_HOST) && (host != VSPI_HOST)) {
|
||||
mp_raise_ValueError("SPI host must be either HSPI(1) or VSPI(2)");
|
||||
}
|
||||
#endif
|
||||
@@ -147,33 +172,70 @@ STATIC void machine_hw_spi_init_internal(
|
||||
if (bus_state == -3) {
|
||||
mp_raise_ValueError("SPI host already used by display driver");
|
||||
}
|
||||
else if (bus_state < 0) {
|
||||
else if (bus_state == -1) {
|
||||
mp_raise_ValueError("SPI host already used with different configuration");
|
||||
}
|
||||
self->host = host;
|
||||
changed |= 0x0004;
|
||||
else if (bus_state == -2) {
|
||||
mp_raise_ValueError("SPI host not available");
|
||||
}
|
||||
if ((host != pold_self->host) || (bus_state != 0)) {
|
||||
self->host = host;
|
||||
changed |= 0x0004;
|
||||
}
|
||||
}
|
||||
if ((baudrate > 0) && (baudrate != self->devcfg.clock_speed_hz)) {
|
||||
if (baudrate == 0) {
|
||||
mp_raise_ValueError("SPI baudrate must be >0");
|
||||
|
||||
if ((baudrate > 0) && (baudrate != pold_self->devcfg.clock_speed_hz)) {
|
||||
// Speed changed
|
||||
if ((baudrate <= 0) || (baudrate > 80000000)) {
|
||||
mp_raise_ValueError("SPI baudrate must be >0 & <=80000000");
|
||||
}
|
||||
self->devcfg.clock_speed_hz = baudrate;
|
||||
changed |= 0x0008;
|
||||
}
|
||||
if ((polarity > -1) && (polarity != self->polarity)) {
|
||||
|
||||
if ((polarity > -1) && (polarity != pold_self->polarity)) {
|
||||
// Polarity changed
|
||||
self->polarity = polarity & 1;
|
||||
changed |= 0x0010;
|
||||
}
|
||||
if ((phase > -1) && (phase != self->phase)) {
|
||||
|
||||
if ((phase > -1) && (phase != pold_self->phase)) {
|
||||
// Phase changed
|
||||
self->phase = phase & 1;
|
||||
changed |= 0x0020;
|
||||
}
|
||||
if ((firstbit > -1) && (firstbit != self->firstbit)) {
|
||||
|
||||
if ((firstbit > -1) && (firstbit != pold_self->firstbit)) {
|
||||
self->firstbit = firstbit & 1;
|
||||
changed |= 0x0040;
|
||||
}
|
||||
|
||||
if (bus_state > 0) {
|
||||
if ((cs > -1) && (cs != pold_self->spi.cs)) {
|
||||
// Initialize CS
|
||||
gpio_pad_select_gpio(cs);
|
||||
gpio_set_direction(cs, GPIO_MODE_OUTPUT);
|
||||
gpio_set_level(cs, 1);
|
||||
self->spi.cs = cs;
|
||||
changed |= 0x0400;
|
||||
}
|
||||
|
||||
if ((duplex > -1) && (duplex != pold_self->duplex)) {
|
||||
// Duplex changed
|
||||
self->duplex = duplex & 1;
|
||||
changed |= 0x0800;
|
||||
}
|
||||
|
||||
if (!changed) return; // no configuration changes, return
|
||||
|
||||
if (pold_self->state == MACHINE_HW_SPI_STATE_INIT) {
|
||||
// Remove device from spi host
|
||||
self->state = MACHINE_HW_SPI_STATE_DEINIT;
|
||||
machine_hw_spi_deinit_internal(pold_self, 0);
|
||||
}
|
||||
|
||||
// Check if spi bus has to be initialized
|
||||
if (MPy_SPIbus[self->host]->mosi_io_num < 0) {
|
||||
// SPI bus not initialized
|
||||
gpio_pad_select_gpio(miso);
|
||||
gpio_pad_select_gpio(mosi);
|
||||
gpio_pad_select_gpio(sck);
|
||||
@@ -181,7 +243,7 @@ STATIC void machine_hw_spi_init_internal(
|
||||
gpio_set_pull_mode(miso, GPIO_PULLUP_ONLY);
|
||||
gpio_set_direction(mosi, GPIO_MODE_OUTPUT);
|
||||
gpio_set_direction(sck, GPIO_MODE_OUTPUT);
|
||||
// SPI bus is free
|
||||
|
||||
MPy_SPIbus[self->host]->sclk_io_num = sck;
|
||||
MPy_SPIbus[self->host]->mosi_io_num = mosi;
|
||||
MPy_SPIbus[self->host]->miso_io_num = miso;
|
||||
@@ -194,28 +256,11 @@ STATIC void machine_hw_spi_init_internal(
|
||||
mp_raise_msg(&mp_type_OSError, "error initializing spi bus");
|
||||
return;
|
||||
}
|
||||
changed |= 0x1000;
|
||||
}
|
||||
|
||||
if ((cs > -1) && (cs != self->spi.cs)) {
|
||||
gpio_pad_select_gpio(cs);
|
||||
gpio_set_direction(cs, GPIO_MODE_OUTPUT);
|
||||
gpio_set_level(cs, 1);
|
||||
self->spi.cs = cs;
|
||||
changed |= 0x0400;
|
||||
}
|
||||
if ((duplex > -1) && (duplex != self->duplex)) {
|
||||
self->duplex = duplex & 1;
|
||||
changed |= 0x0800;
|
||||
}
|
||||
|
||||
if (!changed) return; // no changes
|
||||
|
||||
if (self->state == MACHINE_HW_SPI_STATE_INIT) {
|
||||
self->state = MACHINE_HW_SPI_STATE_DEINIT;
|
||||
machine_hw_spi_deinit_internal(&old_self);
|
||||
}
|
||||
|
||||
self->devcfg.spics_io_num = -1; // No hw CS pin, we use software CS handling
|
||||
// No hw CS pin, we use software CS handling in this module
|
||||
self->devcfg.spics_io_num = -1;
|
||||
|
||||
self->devcfg.mode = self->phase | (self->polarity << 1);
|
||||
self->devcfg.flags = ((self->firstbit == MICROPY_PY_MACHINE_SPI_LSB) ? SPI_DEVICE_TXBIT_LSBFIRST | SPI_DEVICE_RXBIT_LSBFIRST : 0);
|
||||
@@ -227,6 +272,14 @@ STATIC void machine_hw_spi_init_internal(
|
||||
ret = spi_bus_add_device(self->host, &self->devcfg, &self->spi.handle);
|
||||
|
||||
if (ret == ESP_OK) {
|
||||
ret = spi_device_select(&self->spi, 1);
|
||||
if (ret != ESP_OK) {
|
||||
mp_raise_msg(&mp_type_OSError, "Error selecting device");
|
||||
}
|
||||
ret = spi_device_deselect(&self->spi);
|
||||
if (ret != ESP_OK) {
|
||||
mp_raise_msg(&mp_type_OSError, "Error deselecting device");
|
||||
}
|
||||
self->state = MACHINE_HW_SPI_STATE_INIT;
|
||||
return;
|
||||
}
|
||||
@@ -255,7 +308,7 @@ STATIC mp_obj_t machine_hw_spi_deinit(mp_obj_t self_in)
|
||||
machine_hw_spi_obj_t *self = self_in;
|
||||
if (self->state == MACHINE_HW_SPI_STATE_INIT) {
|
||||
self->state = MACHINE_HW_SPI_STATE_DEINIT;
|
||||
machine_hw_spi_deinit_internal(self);
|
||||
machine_hw_spi_deinit_internal(self, 1);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
@@ -269,10 +322,11 @@ STATIC void machine_hw_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_p
|
||||
if (self->spi.cs < 0) sprintf(scs, "Not used");
|
||||
else sprintf(scs, "%d", self->spi.cs);
|
||||
|
||||
mp_printf(print, "SPI([%s] spihost=%u, baudrate=%u, polarity=%u, phase=%u, firstbit=%s, sck=%d, mosi=%d, miso=%d, cs=%s, duplex=%s)",
|
||||
(self->state == MACHINE_HW_SPI_STATE_INIT) ? "init" : "deinit", self->host,
|
||||
spi_get_speed(&self->spi), self->polarity, self->phase, (self->firstbit) ? "LSB" : "MSB",
|
||||
MPy_SPIbus[self->host]->sclk_io_num, MPy_SPIbus[self->host]->mosi_io_num, MPy_SPIbus[self->host]->miso_io_num, scs, (self->duplex) ? "True" : "False");
|
||||
mp_printf(print, "SPI( %s\n spihost=%s (%s)\n baudrate=%u, polarity=%u, phase=%u, firstbit=%s, duplex=%s\n Pins: sck=%d, mosi=%d, miso=%d, cs=%s\n )",
|
||||
(self->state == MACHINE_HW_SPI_STATE_INIT) ? "INITIALIZED" : "DEINITIALIZED",
|
||||
(self->host == HSPI_HOST) ? "HSPI" : "VSPI", (MPy_SPIbus[self->host]->mosi_io_num < 0) ? "free" : "initialized",
|
||||
spi_get_speed(&self->spi), self->polarity, self->phase, (self->firstbit) ? "LSB" : "MSB", (self->duplex) ? "True" : "False",
|
||||
MPy_SPIbus[self->host]->sclk_io_num, MPy_SPIbus[self->host]->mosi_io_num, MPy_SPIbus[self->host]->miso_io_num, scs);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------
|
||||
@@ -307,7 +361,7 @@ STATIC mp_obj_t machine_hw_spi_init(mp_uint_t n_args, const mp_obj_t *pos_args,
|
||||
|
||||
machine_hw_spi_init_internal(self, args[ARG_spihost].u_int, args[ARG_baudrate].u_int,
|
||||
args[ARG_polarity].u_int, args[ARG_phase].u_int,
|
||||
args[ARG_firstbit].u_int, sck, mosi, miso, cs, args[ARG_duplex].u_bool);
|
||||
args[ARG_firstbit].u_int, sck, mosi, miso, cs, args[ARG_duplex].u_bool, 0);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_spi_init_obj, 0, machine_hw_spi_init);
|
||||
@@ -340,6 +394,7 @@ mp_obj_t machine_hw_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_
|
||||
memset(&self->devcfg, 0, sizeof(spi_device_interface_config_t));
|
||||
|
||||
self->spi.cs = -1;
|
||||
self->spi.handle = NULL;
|
||||
int8_t cs = -1;
|
||||
if (args[ARG_cs].u_obj != MP_OBJ_NULL) cs = machine_pin_get_gpio(args[ARG_cs].u_obj);
|
||||
|
||||
@@ -354,7 +409,8 @@ mp_obj_t machine_hw_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_
|
||||
machine_pin_get_gpio(args[ARG_mosi].u_obj),
|
||||
machine_pin_get_gpio(args[ARG_miso].u_obj),
|
||||
cs,
|
||||
args[ARG_duplex].u_bool);
|
||||
args[ARG_duplex].u_bool,
|
||||
1);
|
||||
|
||||
return MP_OBJ_FROM_PTR(self);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Damien P. George
|
||||
* Copyright (c) 2018 LoBo (https://github.com/loboris)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -23,6 +24,7 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "driver/ledc.h"
|
||||
#include "esp_err.h"
|
||||
@@ -30,8 +32,12 @@
|
||||
#include "py/nlr.h"
|
||||
#include "py/runtime.h"
|
||||
#include "modmachine.h"
|
||||
#include "machine_pin.h"
|
||||
#include "mphalport.h"
|
||||
|
||||
// High speed mode
|
||||
#define PWMODE (LEDC_HIGH_SPEED_MODE)
|
||||
|
||||
// Forward dec'l
|
||||
extern const mp_obj_type_t machine_pwm_type;
|
||||
|
||||
@@ -40,50 +46,44 @@ typedef struct _esp32_pwm_obj_t {
|
||||
gpio_num_t pin;
|
||||
uint8_t active;
|
||||
uint8_t channel;
|
||||
uint8_t duty;
|
||||
ledc_timer_config_t timer_cfg;
|
||||
} esp32_pwm_obj_t;
|
||||
|
||||
// Which channel has which GPIO pin assigned?
|
||||
// (-1 if not assigned)
|
||||
STATIC int chan_gpio[LEDC_CHANNEL_MAX];
|
||||
STATIC int chan_gpio[LEDC_CHANNEL_MAX/2];
|
||||
|
||||
// Params for PW operation
|
||||
// 5khz
|
||||
#define PWFREQ (5000)
|
||||
// High speed mode
|
||||
#define PWMODE (LEDC_HIGH_SPEED_MODE)
|
||||
// 10-bit resolution (compatible with esp8266 PWM)
|
||||
#define PWRES (LEDC_TIMER_10_BIT)
|
||||
// Timer 1
|
||||
#define PWTIMER (LEDC_TIMER_1)
|
||||
|
||||
// Config of timer upon which we run all PWM'ed GPIO pins
|
||||
STATIC bool pwm_inited = false;
|
||||
STATIC ledc_timer_config_t timer_cfg = {
|
||||
.bit_num = PWRES,
|
||||
.freq_hz = PWFREQ,
|
||||
.speed_mode = PWMODE,
|
||||
.timer_num = PWTIMER
|
||||
};
|
||||
|
||||
STATIC void pwm_init(void) {
|
||||
//----------------------------------------------------
|
||||
STATIC int set_freq(esp32_pwm_obj_t *self, int newval)
|
||||
{
|
||||
int oval = self->timer_cfg.freq_hz;
|
||||
int ores = self->timer_cfg.duty_resolution;
|
||||
int dperc = (self->duty * 100) / (2 << self->timer_cfg.duty_resolution);
|
||||
|
||||
// Initial condition: no channels assigned
|
||||
for (int x = 0; x < LEDC_CHANNEL_MAX; ++x) {
|
||||
chan_gpio[x] = -1;
|
||||
// Adjust duty resolution
|
||||
int dres = 15;
|
||||
while (newval > (80000000 / (1 << dres))) {
|
||||
dres--;
|
||||
if (dres == 0) break;
|
||||
}
|
||||
if (dres == 0) return 0;
|
||||
|
||||
// Init with default timer params
|
||||
ledc_timer_config(&timer_cfg);
|
||||
}
|
||||
|
||||
STATIC int set_freq(int newval) {
|
||||
int oval = timer_cfg.freq_hz;
|
||||
|
||||
timer_cfg.freq_hz = newval;
|
||||
if (ledc_timer_config(&timer_cfg) != ESP_OK) {
|
||||
timer_cfg.freq_hz = oval;
|
||||
self->timer_cfg.duty_resolution = dres;
|
||||
self->timer_cfg.freq_hz = newval;
|
||||
if (ledc_timer_config(&self->timer_cfg) != ESP_OK) {
|
||||
self->timer_cfg.freq_hz = oval;
|
||||
self->timer_cfg.duty_resolution = ores;
|
||||
return 0;
|
||||
}
|
||||
if (dres != ores) {
|
||||
// Adjust
|
||||
int dval = (dperc * (2 << self->timer_cfg.duty_resolution)) / 100;
|
||||
ledc_set_duty(PWMODE, self->channel, dval);
|
||||
ledc_update_duty(PWMODE, self->channel);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -91,18 +91,24 @@ STATIC int set_freq(int newval) {
|
||||
|
||||
// MicroPython bindings for PWM
|
||||
|
||||
STATIC void esp32_pwm_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
//------------------------------------------------------------------------------------------
|
||||
STATIC void esp32_pwm_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind)
|
||||
{
|
||||
esp32_pwm_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_printf(print, "PWM(%u", self->pin);
|
||||
mp_printf(print, "PWM(pin: %u", self->pin);
|
||||
if (self->active) {
|
||||
mp_printf(print, ", freq=%u, duty=%u", timer_cfg.freq_hz,
|
||||
ledc_get_duty(PWMODE, self->channel));
|
||||
int duty = ledc_get_duty(PWMODE, self->channel);
|
||||
int dperc = (duty * 100) / (1 << self->timer_cfg.duty_resolution);
|
||||
mp_printf(print, ", freq=%u Hz, duty=%u%% [%d], duty resolution=%d bits, channel=%d",
|
||||
ledc_get_freq(PWMODE, self->timer_cfg.timer_num), dperc, duty,
|
||||
self->timer_cfg.duty_resolution, self->channel);
|
||||
}
|
||||
mp_printf(print, ")");
|
||||
}
|
||||
|
||||
STATIC void esp32_pwm_init_helper(esp32_pwm_obj_t *self,
|
||||
size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
STATIC void esp32_pwm_init_helper(esp32_pwm_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args)
|
||||
{
|
||||
enum { ARG_freq, ARG_duty };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_freq, MP_ARG_INT, {.u_int = -1} },
|
||||
@@ -115,77 +121,103 @@ STATIC void esp32_pwm_init_helper(esp32_pwm_obj_t *self,
|
||||
int channel;
|
||||
int avail = -1;
|
||||
|
||||
// Find a free PWM channel, also spot if our pin is
|
||||
// already mentioned.
|
||||
for (channel = 0; channel < LEDC_CHANNEL_MAX; ++channel) {
|
||||
if (chan_gpio[channel] == self->pin) {
|
||||
break;
|
||||
}
|
||||
if ((avail == -1) && (chan_gpio[channel] == -1)) {
|
||||
avail = channel;
|
||||
}
|
||||
}
|
||||
if (channel >= LEDC_CHANNEL_MAX) {
|
||||
if (avail == -1) {
|
||||
mp_raise_ValueError("out of PWM channels");
|
||||
}
|
||||
channel = avail;
|
||||
}
|
||||
self->channel = channel;
|
||||
if (self->channel >= LEDC_CHANNEL_MAX/2) {
|
||||
// New PWM assignment, find a free PWM channel
|
||||
for (channel = 0; channel < LEDC_CHANNEL_MAX/2; ++channel) {
|
||||
if (chan_gpio[channel] == -1) {
|
||||
avail = channel;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Check if pin already used
|
||||
for (channel = 0; channel < LEDC_CHANNEL_MAX/2; ++channel) {
|
||||
if (chan_gpio[channel] == self->pin) {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "pin %d already used for pwm", self->pin));
|
||||
}
|
||||
}
|
||||
// Find a free PWM channel
|
||||
for (channel = 0; channel < LEDC_CHANNEL_MAX/2; ++channel) {
|
||||
if (chan_gpio[channel] == -1) {
|
||||
avail = channel;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (avail == -1) {
|
||||
mp_raise_ValueError("out of PWM channels");
|
||||
}
|
||||
self->channel = channel;
|
||||
|
||||
// New PWM assignment
|
||||
self->active = 1;
|
||||
if (chan_gpio[channel] == -1) {
|
||||
ledc_channel_config_t cfg = {
|
||||
.channel = channel,
|
||||
.duty = (1 << PWRES) / 2,
|
||||
.gpio_num = self->pin,
|
||||
.intr_type = LEDC_INTR_DISABLE,
|
||||
.speed_mode = PWMODE,
|
||||
.timer_sel = PWTIMER,
|
||||
};
|
||||
if (ledc_channel_config(&cfg) != ESP_OK) {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
|
||||
"PWM not supported on pin %d", self->pin));
|
||||
}
|
||||
chan_gpio[channel] = self->pin;
|
||||
// Setup timer
|
||||
self->active = 1;
|
||||
if (chan_gpio[channel] == -1) {
|
||||
// Init timer
|
||||
self->timer_cfg.duty_resolution = LEDC_TIMER_12_BIT; // 12 bits duty resolution
|
||||
self->timer_cfg.freq_hz = 5000; // 5 kHz frequency
|
||||
self->timer_cfg.speed_mode = PWMODE;
|
||||
self->timer_cfg.timer_num = channel;
|
||||
if (ledc_timer_config(&self->timer_cfg) != ESP_OK) {
|
||||
mp_raise_ValueError("Error configuring pwm timer");
|
||||
}
|
||||
|
||||
self->duty = 50;
|
||||
ledc_channel_config_t cfg = {
|
||||
.channel = channel,
|
||||
.duty = (1 << self->timer_cfg.duty_resolution) / 2, // 50%
|
||||
.gpio_num = self->pin,
|
||||
.intr_type = LEDC_INTR_DISABLE,
|
||||
.speed_mode = PWMODE,
|
||||
.timer_sel = channel,
|
||||
};
|
||||
if (ledc_channel_config(&cfg) != ESP_OK) {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "PWM not supported on pin %d", self->pin));
|
||||
}
|
||||
chan_gpio[channel] = self->pin;
|
||||
}
|
||||
}
|
||||
else channel = self->channel;
|
||||
|
||||
// Maybe change PWM timer
|
||||
int tval = args[ARG_freq].u_int;
|
||||
if (tval != -1) {
|
||||
if (tval != timer_cfg.freq_hz) {
|
||||
if (!set_freq(tval)) {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
|
||||
"Bad frequency %d", tval));
|
||||
if (tval != self->timer_cfg.freq_hz) {
|
||||
if (!set_freq(self, tval)) {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Bad frequency %d", tval));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set duty cycle?
|
||||
int dval = args[ARG_duty].u_int;
|
||||
if (dval != -1) {
|
||||
dval &= ((1 << PWRES)-1);
|
||||
int dperc = args[ARG_duty].u_int;
|
||||
if (dperc != -1) {
|
||||
if ((dperc < 0) || (dperc > 100)) {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Bad duty %d, use 0 ~ 100 (%%)", dperc));
|
||||
}
|
||||
// Calculate duty value
|
||||
int dval = (dperc * (2 << self->timer_cfg.duty_resolution)) / 100;
|
||||
ledc_set_duty(PWMODE, channel, dval);
|
||||
ledc_update_duty(PWMODE, channel);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC mp_obj_t esp32_pwm_make_new(const mp_obj_type_t *type,
|
||||
size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
//-------------------------------------------------------------------------------------------------------------
|
||||
STATIC mp_obj_t esp32_pwm_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args)
|
||||
{
|
||||
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
|
||||
gpio_num_t pin_id = machine_pin_get_id(args[0]);
|
||||
gpio_num_t pin_id = machine_pin_get_gpio(args[0]);
|
||||
|
||||
// create PWM object from the given pin
|
||||
esp32_pwm_obj_t *self = m_new_obj(esp32_pwm_obj_t);
|
||||
self->base.type = &machine_pwm_type;
|
||||
self->pin = pin_id;
|
||||
self->active = 0;
|
||||
self->channel = -1;
|
||||
self->channel = LEDC_CHANNEL_MAX;
|
||||
|
||||
// start the PWM subsystem if it's not already running
|
||||
if (!pwm_inited) {
|
||||
pwm_init();
|
||||
// Initial condition: no channels assigned
|
||||
for (int x = 0; x < LEDC_CHANNEL_MAX/2; ++x) {
|
||||
chan_gpio[x] = -1;
|
||||
}
|
||||
pwm_inited = true;
|
||||
}
|
||||
|
||||
@@ -197,19 +229,22 @@ STATIC mp_obj_t esp32_pwm_make_new(const mp_obj_type_t *type,
|
||||
return MP_OBJ_FROM_PTR(self);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t esp32_pwm_init(size_t n_args,
|
||||
const mp_obj_t *args, mp_map_t *kw_args) {
|
||||
//------------------------------------------------------------------------------------
|
||||
STATIC mp_obj_t esp32_pwm_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args)
|
||||
{
|
||||
esp32_pwm_init_helper(args[0], n_args - 1, args + 1, kw_args);
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_KW(esp32_pwm_init_obj, 1, esp32_pwm_init);
|
||||
|
||||
STATIC mp_obj_t esp32_pwm_deinit(mp_obj_t self_in) {
|
||||
//------------------------------------------------
|
||||
STATIC mp_obj_t esp32_pwm_deinit(mp_obj_t self_in)
|
||||
{
|
||||
esp32_pwm_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
int chan = self->channel;
|
||||
|
||||
// Valid channel?
|
||||
if ((chan >= 0) && (chan < LEDC_CHANNEL_MAX)) {
|
||||
if ((chan >= 0) && (chan < LEDC_CHANNEL_MAX/2)) {
|
||||
// Mark it unused, and tell the hardware to stop routing
|
||||
chan_gpio[chan] = -1;
|
||||
ledc_stop(PWMODE, chan, 0);
|
||||
@@ -220,54 +255,89 @@ STATIC mp_obj_t esp32_pwm_deinit(mp_obj_t self_in) {
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_pwm_deinit_obj, esp32_pwm_deinit);
|
||||
|
||||
STATIC mp_obj_t esp32_pwm_freq(size_t n_args, const mp_obj_t *args) {
|
||||
//-----------------------------------------------------------------
|
||||
STATIC mp_obj_t esp32_pwm_freq(size_t n_args, const mp_obj_t *args)
|
||||
{
|
||||
esp32_pwm_obj_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||
|
||||
if (n_args == 1) {
|
||||
// get
|
||||
return MP_OBJ_NEW_SMALL_INT(timer_cfg.freq_hz);
|
||||
return MP_OBJ_NEW_SMALL_INT(self->timer_cfg.freq_hz);
|
||||
}
|
||||
|
||||
// set
|
||||
int tval = mp_obj_get_int(args[1]);
|
||||
if (!set_freq(tval)) {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
|
||||
"Bad frequency %d", tval));
|
||||
if (!set_freq(self, tval)) {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Bad frequency %d", tval));
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp32_pwm_freq_obj, 1, 2, esp32_pwm_freq);
|
||||
|
||||
STATIC mp_obj_t esp32_pwm_duty(size_t n_args, const mp_obj_t *args) {
|
||||
//-----------------------------------------------------------------
|
||||
STATIC mp_obj_t esp32_pwm_duty(size_t n_args, const mp_obj_t *args)
|
||||
{
|
||||
esp32_pwm_obj_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||
int duty;
|
||||
int dperc, duty;
|
||||
|
||||
if (n_args == 1) {
|
||||
// get
|
||||
// get duty
|
||||
duty = ledc_get_duty(PWMODE, self->channel);
|
||||
return MP_OBJ_NEW_SMALL_INT(duty);
|
||||
dperc = (duty * 100) / (1 << self->timer_cfg.duty_resolution);
|
||||
return MP_OBJ_NEW_SMALL_INT(dperc);
|
||||
}
|
||||
|
||||
// set
|
||||
duty = mp_obj_get_int(args[1]);
|
||||
duty &= ((1 << PWRES)-1);
|
||||
ledc_set_duty(PWMODE, self->channel, duty);
|
||||
ledc_update_duty(PWMODE, self->channel);
|
||||
dperc = mp_obj_get_int(args[1]);
|
||||
if (dperc != -1) {
|
||||
if ((dperc < 0) || (dperc > 100)) {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Bad duty %d, use 0 ~ 100 (%%)", dperc));
|
||||
}
|
||||
// Calculate duty value
|
||||
duty = (dperc * (1 << self->timer_cfg.duty_resolution)) / 100;
|
||||
ledc_set_duty(PWMODE, self->channel, duty);
|
||||
ledc_update_duty(PWMODE, self->channel);
|
||||
self->duty = dperc;
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp32_pwm_duty_obj,
|
||||
1, 2, esp32_pwm_duty);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp32_pwm_duty_obj, 1, 2, esp32_pwm_duty);
|
||||
|
||||
//-----------------------------------------------
|
||||
STATIC mp_obj_t esp32_pwm_pause(mp_obj_t self_in)
|
||||
{
|
||||
esp32_pwm_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
ledc_timer_pause(PWMODE, self->timer_cfg.timer_num);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_pwm_pause_obj, esp32_pwm_pause);
|
||||
|
||||
//------------------------------------------------
|
||||
STATIC mp_obj_t esp32_pwm_resume(mp_obj_t self_in)
|
||||
{
|
||||
esp32_pwm_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
ledc_timer_resume(PWMODE, self->timer_cfg.timer_num);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_pwm_resume_obj, esp32_pwm_resume);
|
||||
|
||||
|
||||
|
||||
//==============================================================
|
||||
STATIC const mp_rom_map_elem_t esp32_pwm_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&esp32_pwm_init_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&esp32_pwm_deinit_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&esp32_pwm_freq_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_duty), MP_ROM_PTR(&esp32_pwm_duty_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_pause), MP_ROM_PTR(&esp32_pwm_pause_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_resume), MP_ROM_PTR(&esp32_pwm_resume_obj) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(esp32_pwm_locals_dict, esp32_pwm_locals_dict_table);
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(esp32_pwm_locals_dict,
|
||||
esp32_pwm_locals_dict_table);
|
||||
|
||||
//======================================
|
||||
const mp_obj_type_t machine_pwm_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_PWM,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// MicroPython version info
|
||||
#define MICROPY_GIT_TAG "ESP32_LoBo_v3.1.0"
|
||||
#define MICROPY_GIT_HASH "g1837a034"
|
||||
#define MICROPY_BUILD_DATE "2017-01-03"
|
||||
#define MICROPY_GIT_TAG "ESP32_LoBo_v3.1.1"
|
||||
#define MICROPY_GIT_HASH "ga1b59679"
|
||||
#define MICROPY_BUILD_DATE "2017-01-07"
|
||||
#define MICROPY_VERSION_MAJOR (3)
|
||||
#define MICROPY_VERSION_MINOR (1)
|
||||
#define MICROPY_VERSION_MICRO (0)
|
||||
#define MICROPY_VERSION_STRING "3.1.0"
|
||||
#define MICROPY_VERSION_MICRO (1)
|
||||
#define MICROPY_VERSION_STRING "3.1.1"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Executable
+69
@@ -0,0 +1,69 @@
|
||||
#!/bin/bash
|
||||
|
||||
# BUILD standard firmwares
|
||||
|
||||
mv -f sdkconfig sdkconfig.bkp
|
||||
|
||||
# Build firmwaware for esp32, no psRAM, no OTA
|
||||
cp sdkconfig.fw_esp32 sdkconfig
|
||||
./BUILD.sh -j8 clean all
|
||||
if [ $? -ne 0 ]; then
|
||||
mv -f sdkconfig.bkp sckconfig
|
||||
exit 1
|
||||
fi
|
||||
./BUILD.sh -fs 1024 flash > /dev/null 2>&1
|
||||
./BUILD.sh firmware
|
||||
if [ $? -ne 0 ]; then
|
||||
mv -f sdkconfig.bkp sckconfig
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Build firmwaware for esp32, no psRAM, OTA
|
||||
cp sdkconfig.fw_esp32_ota sdkconfig
|
||||
./BUILD.sh -j8 clean all
|
||||
if [ $? -ne 0 ]; then
|
||||
mv -f sdkconfig.bkp sckconfig
|
||||
exit 1
|
||||
fi
|
||||
./BUILD.sh -fs 1024 flash > /dev/null 2>&1
|
||||
./BUILD.sh firmware
|
||||
if [ $? -ne 0 ]; then
|
||||
mv -f sdkconfig.bkp sckconfig
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Build firmwaware for esp32, psRAM, no OTA
|
||||
cp sdkconfig.fw_psram sdkconfig
|
||||
./BUILD.sh -j8 clean all
|
||||
if [ $? -ne 0 ]; then
|
||||
mv -f sdkconfig.bkp sckconfig
|
||||
exit 1
|
||||
fi
|
||||
./BUILD.sh -fs 1024 flash > /dev/null 2>&1
|
||||
./BUILD.sh firmware
|
||||
if [ $? -ne 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Build firmwaware for esp32, psRAM, OTA
|
||||
cp sdkconfig.fw_psram_ota sdkconfig
|
||||
./BUILD.sh -j8 clean all
|
||||
if [ $? -ne 0 ]; then
|
||||
mv -f sdkconfig.bkp sckconfig
|
||||
exit 1
|
||||
fi
|
||||
./BUILD.sh -fs 1024 flash > /dev/null 2>&1
|
||||
./BUILD.sh firmware
|
||||
if [ $? -ne 0 ]; then
|
||||
mv -f sdkconfig.bkp sckconfig
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mv -f sdkconfig.bkp sckconfig
|
||||
|
||||
cd firmware
|
||||
rm -f MicroPython_LoBo_Firmwares.zip > /dev/null 2>&1
|
||||
zip MicroPython_LoBo_Firmwares.zip -9 -r esp32 esp32_ota esp32_psram esp32_psram_ota README.md
|
||||
|
||||
cd ..
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user