2016-09-16 10:10:18 +02:00
|
|
|
#include "platform.h"
|
2016-09-20 05:35:56 +02:00
|
|
|
#include "driver/console.h"
|
2017-01-11 15:28:10 +01:00
|
|
|
#include "driver/sigmadelta.h"
|
2016-09-20 05:35:56 +02:00
|
|
|
#include <stdio.h>
|
2016-09-16 10:10:18 +02:00
|
|
|
|
|
|
|
int platform_init (void)
|
|
|
|
{
|
|
|
|
return PLATFORM_OK;
|
|
|
|
}
|
|
|
|
|
2017-01-16 21:33:30 +01:00
|
|
|
|
|
|
|
// *****************************************************************************
|
|
|
|
// GPIO subsection
|
|
|
|
|
|
|
|
int platform_gpio_exists( unsigned gpio ) { return GPIO_IS_VALID_GPIO(gpio); }
|
|
|
|
int platform_gpio_output_exists( unsigned gpio ) { return GPIO_IS_VALID_OUTPUT_GPIO(gpio); }
|
|
|
|
|
|
|
|
|
2016-09-16 10:10:18 +02:00
|
|
|
// ****************************************************************************
|
|
|
|
// UART
|
|
|
|
|
|
|
|
uint32_t platform_uart_setup( unsigned id, uint32_t baud, int databits, int parity, int stopbits )
|
|
|
|
{
|
2016-09-20 05:35:56 +02:00
|
|
|
if (id == CONSOLE_UART)
|
2016-09-16 10:10:18 +02:00
|
|
|
{
|
2016-09-20 05:35:56 +02:00
|
|
|
ConsoleSetup_t cfg;
|
|
|
|
cfg.bit_rate = baud;
|
|
|
|
switch (databits)
|
|
|
|
{
|
|
|
|
case 5: cfg.data_bits = CONSOLE_NUM_BITS_5; break;
|
|
|
|
case 6: cfg.data_bits = CONSOLE_NUM_BITS_6; break;
|
|
|
|
case 7: cfg.data_bits = CONSOLE_NUM_BITS_7; break;
|
|
|
|
case 8: // fall-through
|
|
|
|
default: cfg.data_bits = CONSOLE_NUM_BITS_8; break;
|
|
|
|
}
|
|
|
|
switch (parity)
|
|
|
|
{
|
|
|
|
case PLATFORM_UART_PARITY_EVEN: cfg.parity = CONSOLE_PARITY_EVEN; break;
|
|
|
|
case PLATFORM_UART_PARITY_ODD: cfg.parity = CONSOLE_PARITY_ODD; break;
|
|
|
|
default: // fall-through
|
|
|
|
case PLATFORM_UART_PARITY_NONE: cfg.parity = CONSOLE_PARITY_NONE; break;
|
|
|
|
}
|
|
|
|
switch (stopbits)
|
|
|
|
{
|
|
|
|
default: // fall-through
|
|
|
|
case PLATFORM_UART_STOPBITS_1:
|
|
|
|
cfg.stop_bits = CONSOLE_STOP_BITS_1; break;
|
|
|
|
case PLATFORM_UART_STOPBITS_1_5:
|
|
|
|
cfg.stop_bits = CONSOLE_STOP_BITS_1_5; break;
|
|
|
|
case PLATFORM_UART_STOPBITS_2:
|
|
|
|
cfg.stop_bits = CONSOLE_STOP_BITS_2; break;
|
|
|
|
}
|
|
|
|
cfg.auto_baud = false;
|
|
|
|
console_setup (&cfg);
|
|
|
|
return baud;
|
2016-09-16 10:10:18 +02:00
|
|
|
}
|
2016-09-20 05:35:56 +02:00
|
|
|
else
|
2016-09-16 10:10:18 +02:00
|
|
|
{
|
2016-09-20 05:35:56 +02:00
|
|
|
printf("UART1/UART2 not yet supported\n");
|
|
|
|
return 0;
|
2016-09-16 10:10:18 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void platform_uart_send( unsigned id, uint8_t data )
|
|
|
|
{
|
2016-09-20 05:35:56 +02:00
|
|
|
if (id == CONSOLE_UART)
|
|
|
|
putchar (data);
|
2016-09-16 10:10:18 +02:00
|
|
|
}
|
2017-01-11 15:28:10 +01:00
|
|
|
|
2017-04-18 22:43:03 +02:00
|
|
|
void platform_uart_flush( unsigned id )
|
|
|
|
{
|
|
|
|
if (id == CONSOLE_UART)
|
|
|
|
fflush (stdout);
|
|
|
|
}
|
|
|
|
|
2017-01-11 15:28:10 +01:00
|
|
|
// *****************************************************************************
|
|
|
|
// Sigma-Delta platform interface
|
|
|
|
|
|
|
|
static gpio_num_t platform_sigma_delta_channel2gpio[SIGMADELTA_CHANNEL_MAX];
|
|
|
|
|
|
|
|
int platform_sigma_delta_exists( unsigned channel ) {
|
|
|
|
return (channel < SIGMADELTA_CHANNEL_MAX);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t platform_sigma_delta_setup( uint8_t channel, uint8_t gpio_num )
|
|
|
|
{
|
|
|
|
#if 0
|
|
|
|
// signal generator can't be stopped this way
|
|
|
|
// stop signal generator
|
|
|
|
if (ESP_OK != sigmadelta_set_prescale( channel, 0 ))
|
|
|
|
return 0;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// note channel to gpio assignment
|
|
|
|
platform_sigma_delta_channel2gpio[channel] = gpio_num;
|
|
|
|
|
|
|
|
return ESP_OK == sigmadelta_set_pin( channel, gpio_num ) ? 1 : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t platform_sigma_delta_close( uint8_t channel )
|
|
|
|
{
|
|
|
|
#if 0
|
|
|
|
// Note: signal generator can't be stopped this way
|
|
|
|
// stop signal generator
|
|
|
|
if (ESP_OK != sigmadelta_set_prescale( channel, 0 ))
|
|
|
|
return 0;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
gpio_set_level( platform_sigma_delta_channel2gpio[channel], 1 );
|
|
|
|
gpio_config_t cfg;
|
|
|
|
// force pin back to GPIO
|
|
|
|
cfg.intr_type = GPIO_INTR_DISABLE;
|
|
|
|
cfg.mode = GPIO_MODE_OUTPUT; // essential to switch IO matrix to GPIO
|
|
|
|
cfg.pull_down_en = GPIO_PULLDOWN_DISABLE;
|
|
|
|
cfg.pull_up_en = GPIO_PULLUP_ENABLE;
|
|
|
|
cfg.pin_bit_mask = 1 << platform_sigma_delta_channel2gpio[channel];
|
|
|
|
if (ESP_OK != gpio_config( &cfg ))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
// and set it finally to input with pull-up enabled
|
|
|
|
cfg.mode = GPIO_MODE_INPUT;
|
|
|
|
|
|
|
|
return ESP_OK == gpio_config( &cfg ) ? 1 : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
// PWM emulation not possible, code kept for future reference
|
|
|
|
uint8_t platform_sigma_delta_set_pwmduty( uint8_t channel, uint8_t duty )
|
|
|
|
{
|
|
|
|
uint8_t target = 0, prescale = 0;
|
|
|
|
|
|
|
|
target = duty > 128 ? 256 - duty : duty;
|
|
|
|
prescale = target == 0 ? 0 : target-1;
|
|
|
|
|
|
|
|
//freq = 80000 (khz) /256 /duty_target * (prescale+1)
|
|
|
|
if (ESP_OK != sigmadelta_set_prescale( channel, prescale ))
|
|
|
|
return 0;
|
|
|
|
if (ESP_OK != sigmadelta_set_duty( channel, duty-128 ))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
uint8_t platform_sigma_delta_set_prescale( uint8_t channel, uint8_t prescale )
|
|
|
|
{
|
|
|
|
return ESP_OK == sigmadelta_set_prescale( channel, prescale ) ? 1 : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t IRAM_ATTR platform_sigma_delta_set_duty( uint8_t channel, int8_t duty )
|
|
|
|
{
|
|
|
|
return ESP_OK == sigmadelta_set_duty( channel, duty ) ? 1 : 0;
|
|
|
|
}
|
2017-01-16 21:33:30 +01:00
|
|
|
|
|
|
|
// *****************************************************************************
|
|
|
|
// I2C platform interface
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
// platform functions for the IDF I2C driver
|
|
|
|
// they're currently deactivated because of https://github.com/espressif/esp-idf/issues/241
|
|
|
|
// long-term goal is to use these instead of the SW driver in the #else branch
|
|
|
|
|
|
|
|
#include "driver/i2c.h"
|
|
|
|
int platform_i2c_setup( unsigned id, uint8_t sda, uint8_t scl, uint32_t speed ) {
|
|
|
|
i2c_config_t conf;
|
|
|
|
conf.mode = I2C_MODE_MASTER;
|
|
|
|
conf.sda_io_num = sda;
|
|
|
|
conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
|
|
|
|
conf.scl_io_num = scl;
|
|
|
|
conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
|
|
|
|
conf.master.clk_speed = speed;
|
|
|
|
if (ESP_OK != i2c_param_config( id, &conf ))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (ESP_OK != i2c_driver_install( id, conf.mode, 0, 0, 0 ))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int platform_i2c_send_start( unsigned id ) {
|
|
|
|
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
|
|
|
i2c_master_start( cmd );
|
|
|
|
esp_err_t ret = i2c_master_cmd_begin( id, cmd, 1000 / portTICK_RATE_MS );
|
|
|
|
i2c_cmd_link_delete( cmd );
|
|
|
|
|
|
|
|
return ret == ESP_OK ? 1 : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int platform_i2c_send_stop( unsigned id ) {
|
|
|
|
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
|
|
|
i2c_master_stop( cmd );
|
|
|
|
esp_err_t ret = i2c_master_cmd_begin( id, cmd, 1000 / portTICK_RATE_MS );
|
|
|
|
i2c_cmd_link_delete( cmd );
|
|
|
|
|
|
|
|
return ret == ESP_OK ? 1 : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int platform_i2c_send_address( unsigned id, uint16_t address, int direction, int ack_check_en ) {
|
|
|
|
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
|
|
|
|
|
|
|
direction = ( direction == PLATFORM_I2C_DIRECTION_TRANSMITTER ) ? 0 : 1;
|
|
|
|
|
|
|
|
i2c_master_write_byte( cmd, (uint8_t) ((address << 1) | direction ), ack_check_en );
|
|
|
|
|
|
|
|
esp_err_t ret = i2c_master_cmd_begin( id, cmd, 1000 / portTICK_RATE_MS );
|
|
|
|
i2c_cmd_link_delete( cmd );
|
|
|
|
|
|
|
|
// we return ack (1=acked).
|
|
|
|
if (ret == ESP_FAIL)
|
|
|
|
return 0;
|
|
|
|
else if (ret == ESP_OK)
|
|
|
|
return 1;
|
|
|
|
else
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int platform_i2c_send_byte( unsigned id, uint8_t data, int ack_check_en ) {
|
|
|
|
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
|
|
|
i2c_master_write_byte( cmd, data, ack_check_en );
|
|
|
|
|
|
|
|
esp_err_t ret = i2c_master_cmd_begin( id, cmd, 1000 / portTICK_RATE_MS );
|
|
|
|
i2c_cmd_link_delete( cmd );
|
|
|
|
|
|
|
|
// we return ack (1=acked).
|
|
|
|
if (ret == ESP_FAIL)
|
|
|
|
return 0;
|
|
|
|
else if (ret == ESP_OK)
|
|
|
|
return 1;
|
|
|
|
else
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int platform_i2c_recv_byte( unsigned id, int ack_val ){
|
|
|
|
uint8_t data;
|
|
|
|
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
|
|
|
i2c_master_read_byte( cmd, &data, ack_val > 0 ? 0 : 1 );
|
|
|
|
|
|
|
|
esp_err_t ret = i2c_master_cmd_begin( id, cmd, 1000 / portTICK_RATE_MS );
|
|
|
|
i2c_cmd_link_delete( cmd );
|
|
|
|
|
|
|
|
return ret == ESP_OK ? data : -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
// platform functions for SW-based I2C driver
|
|
|
|
// they work around the issue with the IDF driver
|
|
|
|
// remove when functions for the IDF driver can be used instead
|
|
|
|
|
|
|
|
#include "driver/i2c_sw_master.h"
|
|
|
|
int platform_i2c_setup( unsigned id, uint8_t sda, uint8_t scl, uint32_t speed ){
|
|
|
|
if (!platform_gpio_output_exists(sda) || !platform_gpio_output_exists(scl))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (speed != PLATFORM_I2C_SPEED_SLOW)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
i2c_sw_master_gpio_init(sda, scl);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int platform_i2c_send_start( unsigned id ){
|
|
|
|
i2c_sw_master_start();
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int platform_i2c_send_stop( unsigned id ){
|
|
|
|
i2c_sw_master_stop();
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int platform_i2c_send_address( unsigned id, uint16_t address, int direction, int ack_check_en ){
|
|
|
|
// Convert enum codes to R/w bit value.
|
|
|
|
// If TX == 0 and RX == 1, this test will be removed by the compiler
|
|
|
|
if ( ! ( PLATFORM_I2C_DIRECTION_TRANSMITTER == 0 &&
|
|
|
|
PLATFORM_I2C_DIRECTION_RECEIVER == 1 ) ) {
|
|
|
|
direction = ( direction == PLATFORM_I2C_DIRECTION_TRANSMITTER ) ? 0 : 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
i2c_sw_master_writeByte( (uint8_t) ((address << 1) | direction ));
|
|
|
|
// Low-level returns nack (0=acked); we return ack (1=acked).
|
|
|
|
return ! i2c_sw_master_getAck();
|
|
|
|
}
|
|
|
|
|
|
|
|
int platform_i2c_send_byte( unsigned id, uint8_t data, int ack_check_en ){
|
|
|
|
i2c_sw_master_writeByte(data);
|
|
|
|
// Low-level returns nack (0=acked); we return ack (1=acked).
|
|
|
|
return ! i2c_sw_master_getAck();
|
|
|
|
}
|
|
|
|
|
|
|
|
int platform_i2c_recv_byte( unsigned id, int ack ){
|
|
|
|
uint8_t r = i2c_sw_master_readByte();
|
|
|
|
i2c_sw_master_setAck( !ack );
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
int platform_i2c_exists( unsigned id ) { return id < I2C_NUM_MAX; }
|