/* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */
/*
* File: main.c
* Author: Olaf I. Gomez P.
* Created on: December 18th 2018
* uC: ESP32-WROOM-32
* Version: 1.0
* Description: Main programa
*
*/
/* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */
/* General Includes */
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <sys/unistd.h>
#include <sys/stat.h>
/* Kernel Includes */
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
/* Hardware Includes */
#include "driver/uart.h"
#include "driver/gpio.h"
#include "driver/adc.h"
#include "esp_adc_cal.h"
#include "driver/i2c.h"
#include "SSD1306.h"
#include "font8x8_basic.h"
#include "CGRAM.h"
#include "driver/touch_pad.h"
#include "esp_vfs_fat.h"
#include "driver/sdmmc_host.h"
#include "driver/sdspi_host.h"
#include "sdmmc_cmd.h"
/* Defines RGB */
#define GPIO_OUTPUT_LEDR_IO_12 12
#define GPIO_OUTPUT_LEDG_IO_14 14
#define GPIO_OUTPUT_LEDB_IO_13 13
#define GPIO_OUTPUT_PIN_SEL ( ( 1ULL<<GPIO_OUTPUT_LEDR_IO_12 ) | ( 1ULL<<GPIO_OUTPUT_LEDG_IO_14 ) | ( 1ULL<<GPIO_OUTPUT_LEDB_IO_13 ) )
/* Defines ADC */
#define DEFAULT_VREF 1100 /* Use adc2_vref_to_gpio() to obtain a better estimate */
#define NO_OF_SAMPLES 64 /* Multisampling */
static esp_adc_cal_characteristics_t *adc_chars;
static const adc_channel_t channel = ADC_CHANNEL_7; /* GPIO35 if ADC1 */
static const adc_atten_t atten = ADC_ATTEN_DB_0;
static const adc_unit_t unit = ADC_UNIT_1;
/* Defines UART 1 */
#define EX_UART_NUM UART_NUM_1
#define BUF_SIZE 512
#define GPIO_TX_OUT_1_IO_17 17
#define GPIO_RX_IN_1_IO_16 16
static intr_handle_t handle_console;
/* Receive buffer to collect incoming data */
uint8_t rxbuf[ 256 ];
/* Register to collect data length */
uint16_t urxlen;
bool flag_rx;
uint32_t data_rx_length;
static uint8_t iu;
/* Defines OLED */
#define SDA_PIN 23
#define SCL_PIN 22
/* Defines Touch Pad */
#define TOUCH_THRESH_NO_USE (0)
#define TOUCH_THRESH_PERCENT (80)
#define TOUCHPAD_FILTER_TOUCH_PERIOD (10)
static bool s_pad_activated;
static uint32_t s_pad_init_val;
/* Defines Push Button */
#define GPIO_INPUT_PB_1 34
#define GPIO_INPUT_CD 15
#define GPIO_INPUT_PIN_SEL ( ( 1ULL<<GPIO_INPUT_PB_1 ) | ( 1ULL<<GPIO_INPUT_CD ) )
/* When testing SD and SPI modes, keep in mind that once the card has been */
/* initialized in SPI mode, it can not be reinitialized in SD mode without */
/* toggling power to the card. */
/* Pin mapping when using SPI mode. */
/* With this mapping, SD card can be used both in SPI and 1-line SD mode. */
/* Note that a pull-up on CS line is required in SD mode. */
#define PIN_NUM_MISO 19
#define PIN_NUM_MOSI 18
#define PIN_NUM_CLK 5
#define PIN_NUM_CS 2
bool flag_memory;
/* Function Prototypes */
static void ledRGB_task( void *pvParameters );
static void adc_task ( void *pvParameters );
static void check_efuse();
static void print_char_val_type( esp_adc_cal_value_t val_type );
static void rx_interrupt( void *pvParameters );
static void IRAM_ATTR uart_intr_handle( void *arg );
static void oled( void *pvParameters );
void i2c_master_init( void );
void ssd1306_init( void );
void ssd1306_display_clear( void );
void ssd1306_display_text( const void *arg_text );
void ssd1306_display_pattern( void );
void ssd1306_display_imagen( const uint8_t pointer[] );
static void touchButton( void *pvParameters );
static void tp_example_rtc_intr( void * arg );
static void tp_example_set_thresholds( void );
static void pushButtonSD( void *pvParameters );
void app_main()
{
xTaskCreate( &ledRGB_task , "LED_RGB" , 8192, NULL, 2, NULL );
xTaskCreate( &adc_task , "ADC" , 8192, NULL, 3, NULL );
xTaskCreate( &rx_interrupt, "TX_INT" , 8192, NULL, 1, NULL );
xTaskCreate( &oled , "OLED" , 8192, NULL, 4, NULL );
xTaskCreate( &touchButton , "TOUCHBT" , 8192, NULL, 4, NULL );
xTaskCreate( &pushButtonSD, "PUSHBTSD", 8192, NULL, 4, NULL );
}
/*
*
*/
static void ledRGB_task( void *pvParameters )
{
/* Configuration LED RGB */
gpio_config_t io_conf;
/* disable interrupt */
io_conf.intr_type = GPIO_PIN_INTR_DISABLE;
/* set as output mode */
io_conf.mode = GPIO_MODE_OUTPUT;
/* bit mask of the pins that you want to set,e.g.GPIO18/19 */
io_conf.pin_bit_mask = GPIO_OUTPUT_PIN_SEL;
/* disable pull-down mode */
io_conf.pull_down_en = 0;
/* disable pull-up mode */
io_conf.pull_up_en = 0;
/* configure GPIO with the given settings */
gpio_config( &io_conf );
/* LED Initialization */
gpio_set_level( GPIO_OUTPUT_LEDG_IO_14, 0 );
gpio_set_level( GPIO_OUTPUT_LEDR_IO_12, 0 );
gpio_set_level( GPIO_OUTPUT_LEDB_IO_13, 0 );
/* Variables */
uint8_t cnt_ledrgb;
/* Variables Initialization */
cnt_ledrgb = 0;
for(;;)
{
printf( "Led RGB... \n" );
gpio_set_level( GPIO_OUTPUT_LEDG_IO_14, cnt_ledrgb & 0x01 );
gpio_set_level( GPIO_OUTPUT_LEDR_IO_12, cnt_ledrgb & 0x02 );
gpio_set_level( GPIO_OUTPUT_LEDB_IO_13, cnt_ledrgb & 0x04 );
cnt_ledrgb++;
/* To start a new count */
if( 8 == cnt_ledrgb ) cnt_ledrgb = 0;
vTaskDelay( pdMS_TO_TICKS( 1000 ) );
}
}
/*
*
*/
static void check_efuse()
{
/* Check TP is burned into eFuse */
if ( esp_adc_cal_check_efuse( ESP_ADC_CAL_VAL_EFUSE_TP ) == ESP_OK ) {
printf( "eFuse Two Point: Supported\n" );
} else {
printf( "eFuse Two Point: NOT supported\n" );
}
/* Check Vref is burned into eFuse */
if ( esp_adc_cal_check_efuse( ESP_ADC_CAL_VAL_EFUSE_VREF ) == ESP_OK ) {
printf( "eFuse Vref: Supported\n" );
} else {
printf( "eFuse Vref: NOT supported\n" );
}
}
/*
*
*/
static void print_char_val_type( esp_adc_cal_value_t val_type )
{
if ( val_type == ESP_ADC_CAL_VAL_EFUSE_TP ) {
printf( "Characterized using Two Point Value\n" );
} else if ( val_type == ESP_ADC_CAL_VAL_EFUSE_VREF ) {
printf( "Characterized using eFuse Vref\n" );
} else {
printf( "Characterized using Default Vref\n" );
}
}
/*
*
*/
static void adc_task ( void *pvParameters )
{
/* Configuration ADC 1 */
/* Check if Two Point or Vref are burned into eFuse */
check_efuse();
/* Configure ADC */
if ( unit == ADC_UNIT_1 ) {
adc1_config_width( ADC_WIDTH_BIT_12 );
adc1_config_channel_atten( channel, atten );
} else {
adc2_config_channel_atten( ( adc2_channel_t )channel, atten );
}
/* Characterize ADC */
adc_chars = calloc( 1, sizeof( esp_adc_cal_characteristics_t ) );
esp_adc_cal_value_t val_type = esp_adc_cal_characterize( unit, atten, ADC_WIDTH_BIT_12, DEFAULT_VREF, adc_chars );
print_char_val_type( val_type );
/* Continuously sample ADC1 */
for(;;)
{
uint32_t adc_reading = 0;
/* Multisampling */
for ( int i = 0; i < NO_OF_SAMPLES; i++ ) {
if ( unit == ADC_UNIT_1 ) {
adc_reading += adc1_get_raw( ( adc1_channel_t )channel );
} else {
int raw;
adc2_get_raw( ( adc2_channel_t )channel, ADC_WIDTH_BIT_12, &raw );
adc_reading += raw;
}
}
adc_reading /= NO_OF_SAMPLES;
/* Convert adc_reading to voltage in mV */
uint32_t voltage = esp_adc_cal_raw_to_voltage( adc_reading, adc_chars );
printf("Raw: %d\tVoltage: %dmV\n", adc_reading, voltage);
vTaskDelay( pdMS_TO_TICKS( 1000 ) );
}
}
/*
*
*/
static void rx_interrupt( void *pvParameters )
{
/* Configure parameters of an UART driver,
* communication pins and install the driver */
uart_config_t uart_config = {
.baud_rate = 115200,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
};
ESP_ERROR_CHECK( uart_param_config( EX_UART_NUM, &uart_config ) );
/* Set UART pins (using UART0 default pins ie no changes.) */
ESP_ERROR_CHECK( uart_set_pin ( EX_UART_NUM, GPIO_TX_OUT_1_IO_17, GPIO_RX_IN_1_IO_16, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE ) );
/* Install UART driver, and get the queue. */
ESP_ERROR_CHECK( uart_driver_install( EX_UART_NUM, BUF_SIZE, 0, 0, NULL, 0 ) );
/* release the pre registered UART handler/subroutine */
ESP_ERROR_CHECK( uart_isr_free( EX_UART_NUM ) );
/* register new UART subroutine */
ESP_ERROR_CHECK( uart_isr_register( EX_UART_NUM, uart_intr_handle, NULL, ESP_INTR_FLAG_IRAM, &handle_console ) );
/* enable RX interrupt */
ESP_ERROR_CHECK( uart_enable_rx_intr( EX_UART_NUM ) );
//UART_INTR_MASK
/* Variables Initialization */
flag_rx = false;
data_rx_length = 0;
uint8_t j;
for(;;)
{
printf("Rx Interrupt...\n");
if( true == flag_rx )
{
printf("Data: ");
for( j = 0; j < data_rx_length; j++ )
{
printf("%c", rxbuf[ j ] );
}
printf("\n");
flag_rx = false;
printf("Data Length: %u \n", data_rx_length);
}
vTaskDelay( pdMS_TO_TICKS( 1000 ) );
}
}
/*
* Define UART interrupt subroutine to ackowledge interrupt
*/
static void IRAM_ATTR uart_intr_handle( void *arg )
{
static uint16_t rx_fifo_len;
rx_fifo_len = UART1.status.rxfifo_cnt; /* read number of bytes in UART buffer */
data_rx_length = rx_fifo_len;
iu=0;
while( rx_fifo_len ){
rxbuf[ iu++ ] = UART1.fifo.rw_byte; /* read all bytes */
rx_fifo_len--;
}
flag_rx = true;
/* after reading bytes from buffer clear UART interrupt status */
uart_clear_intr_status( EX_UART_NUM, UART_RXFIFO_FULL_INT_CLR | UART_RXFIFO_TOUT_INT_CLR );
/* a test code or debug code to indicate UART receives successfully,
you can redirect received byte as echo also */
uart_write_bytes( EX_UART_NUM, (const char*) "RX Done\n", 8 );
}
/*
*
*/
static void oled( void *pvParameters )
{
/* To start I2C */
i2c_master_init();
/* To SSD1306 initialization */
ssd1306_init();
for(;;)
{
printf("oled...\n");
/* To clear SSD1306 */
ssd1306_display_clear();
/* Hello World */
ssd1306_display_text( "Hello World!\nHello World!\nHello World!\nHello World!\nHello World!\nHello World!\nHello World!\nHello World!\n" );
vTaskDelay( pdMS_TO_TICKS( 2000 ) );
/* To clear SSD1306 */
ssd1306_display_clear();
/* To create a pattern */
ssd1306_display_pattern();
vTaskDelay( pdMS_TO_TICKS( 2000 ) );
/* To clear SSD1306 */
ssd1306_display_clear();
/* To create a image */
ssd1306_display_imagen( correcaminos );
vTaskDelay( pdMS_TO_TICKS( 2000 ) );
/* To clear SSD1306 */
ssd1306_display_clear();
/* To create a image */
ssd1306_display_imagen( mario );
vTaskDelay( pdMS_TO_TICKS( 2000 ) );
}
}
/*
*
*/
void i2c_master_init( void )
{
/* */
i2c_config_t i2c_config = {
.mode = I2C_MODE_MASTER,
.sda_io_num = SDA_PIN,
.scl_io_num = SCL_PIN,
.sda_pullup_en = GPIO_PULLUP_ENABLE,
.scl_pullup_en = GPIO_PULLUP_ENABLE,
.master.clk_speed = 1000000
};
i2c_param_config( I2C_NUM_0, &i2c_config );
i2c_driver_install( I2C_NUM_0, I2C_MODE_MASTER, 0, 0, 0 );
}
/*
*
*/
void ssd1306_init( void )
{
esp_err_t espRc;
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (OLED_I2C_ADDRESS << 1) | I2C_MASTER_WRITE, true);
i2c_master_write_byte(cmd, OLED_CONTROL_BYTE_CMD_STREAM, true);
i2c_master_write_byte(cmd, OLED_CMD_SET_CHARGE_PUMP, true);
i2c_master_write_byte(cmd, 0x14, true);
i2c_master_write_byte(cmd, OLED_CMD_SET_SEGMENT_REMAP, true); // reverse left-right mapping
i2c_master_write_byte(cmd, OLED_CMD_SET_COM_SCAN_MODE, true); // reverse up-bottom mapping
i2c_master_write_byte(cmd, OLED_CMD_DISPLAY_INVERTED, true);
i2c_master_write_byte(cmd, OLED_CMD_DISPLAY_ON, true);
i2c_master_stop(cmd);
espRc = i2c_master_cmd_begin(I2C_NUM_0, cmd, 10/portTICK_PERIOD_MS);
if (espRc == ESP_OK) {
printf("OLED configured successfully");
} else {
printf("OLED configuration failed. code: 0x%.2X", espRc);
}
i2c_cmd_link_delete(cmd);
}
/*
*
*/
void ssd1306_display_clear( void )
{
i2c_cmd_handle_t cmd;
uint8_t i;
uint8_t zero[128];
/* Clear Variable */
for (i = 0; i < 128; i++)
{
zero[i] = 0;
}
for (i = 0; i < 8; i++)
{
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (OLED_I2C_ADDRESS << 1) | I2C_MASTER_WRITE, true);
i2c_master_write_byte(cmd, OLED_CONTROL_BYTE_CMD_SINGLE, true);
i2c_master_write_byte(cmd, 0xB0 | i, true);
i2c_master_write_byte(cmd, OLED_CONTROL_BYTE_DATA_STREAM, true);
i2c_master_write(cmd, zero, 128, true);
i2c_master_stop(cmd);
i2c_master_cmd_begin(I2C_NUM_0, cmd, 10/portTICK_PERIOD_MS);
i2c_cmd_link_delete(cmd);
}
}
/*
*
*/
void ssd1306_display_text( const void *arg_text )
{
char *text = (char*)arg_text;
uint8_t text_len = strlen(text);
i2c_cmd_handle_t cmd;
uint8_t cur_page = 0;
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (OLED_I2C_ADDRESS << 1) | I2C_MASTER_WRITE, true);
i2c_master_write_byte(cmd, OLED_CONTROL_BYTE_CMD_STREAM, true);
i2c_master_write_byte(cmd, 0x00, true); // reset column
i2c_master_write_byte(cmd, 0x10, true);
i2c_master_write_byte(cmd, 0xB0 | cur_page, true); // reset page
i2c_master_stop(cmd);
i2c_master_cmd_begin(I2C_NUM_0, cmd, 10/portTICK_PERIOD_MS);
i2c_cmd_link_delete(cmd);
for (uint8_t i = 0; i < text_len; i++) {
if (text[i] == '\n') {
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (OLED_I2C_ADDRESS << 1) | I2C_MASTER_WRITE, true);
i2c_master_write_byte(cmd, OLED_CONTROL_BYTE_CMD_STREAM, true);
i2c_master_write_byte(cmd, 0x00, true); // reset column
i2c_master_write_byte(cmd, 0x10, true);
i2c_master_write_byte(cmd, 0xB0 | ++cur_page, true); // increment page
i2c_master_stop(cmd);
i2c_master_cmd_begin(I2C_NUM_0, cmd, 10/portTICK_PERIOD_MS);
i2c_cmd_link_delete(cmd);
} else {
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (OLED_I2C_ADDRESS << 1) | I2C_MASTER_WRITE, true);
i2c_master_write_byte(cmd, OLED_CONTROL_BYTE_DATA_STREAM, true);
i2c_master_write(cmd, font8x8_basic_tr[(uint8_t)text[i]], 8, true);
i2c_master_stop(cmd);
i2c_master_cmd_begin(I2C_NUM_0, cmd, 10/portTICK_PERIOD_MS);
i2c_cmd_link_delete(cmd);
}
}
}
/*
*
*/
void ssd1306_display_pattern( void )
{
i2c_cmd_handle_t cmd;
for ( uint8_t i = 0; i < 8; i++ )
{
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (OLED_I2C_ADDRESS << 1) | I2C_MASTER_WRITE, true);
i2c_master_write_byte(cmd, OLED_CONTROL_BYTE_CMD_SINGLE, true);
i2c_master_write_byte(cmd, 0xB0 | i, true);
i2c_master_write_byte(cmd, OLED_CONTROL_BYTE_DATA_STREAM, true);
for (uint8_t j = 0; j < 128; j++) {
i2c_master_write_byte(cmd, 0xFF >> (j % 8), true);
}
i2c_master_stop(cmd);
i2c_master_cmd_begin(I2C_NUM_0, cmd, 10/portTICK_PERIOD_MS);
i2c_cmd_link_delete(cmd);
}
}
/*
*
*/
void ssd1306_display_imagen( const uint8_t pointer[] )
{
uint16_t u8Column=0;
uint16_t aux = 0;
i2c_cmd_handle_t cmd;
for ( u8Column=0; u8Column<8; u8Column++ )
{
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (OLED_I2C_ADDRESS << 1) | I2C_MASTER_WRITE, true);
i2c_master_write_byte(cmd, OLED_CONTROL_BYTE_CMD_SINGLE, true);
i2c_master_write_byte(cmd, 0xB0 | u8Column, true);
i2c_master_write_byte(cmd, OLED_CONTROL_BYTE_DATA_STREAM, true);
for (uint8_t i = 0; i < 128; i++) {
i2c_master_write_byte(cmd, pointer[ aux + i ] , true);
}
i2c_master_stop(cmd);
i2c_master_cmd_begin(I2C_NUM_0, cmd, 10/portTICK_PERIOD_MS);
i2c_cmd_link_delete(cmd);
aux = aux + 128;
}
}
/*
Handle an interrupt triggered when a pad is touched.
Recognize what pad has been touched and save it in a table.
*/
static void tp_example_rtc_intr( void * arg )
{
uint32_t pad_intr = touch_pad_get_status();
/* clear interrupt */
touch_pad_clear_status();
if ((pad_intr >> 7) & 0x01) {
s_pad_activated = true;
}
}
/*
Read values sensed at all available touch pads.
Use 2 / 3 of read value as the threshold
to trigger interrupt when the pad is touched.
Note: this routine demonstrates a simple way
to configure activation threshold for the touch pads.
Do not touch any pads when this routine
is running (on application start).
*/
static void tp_example_set_thresholds( void )
{
uint16_t touch_value;
/* read filtered value*/
touch_pad_read_filtered( 7, &touch_value );
s_pad_init_val = touch_value;
printf("Test init: touch pad [7] val is %d \n", touch_value);
/* set interrupt threshold. */
ESP_ERROR_CHECK( touch_pad_set_thresh( 7, touch_value * 2 / 3 ) );
}
/*
*
*/
static void touchButton( void *pvParameters )
{
/* To initialization touch pad */
touch_pad_init();
/* If use interrupt trigger mode, should set touch sensor FSM mode at 'TOUCH_FSM_MODE_TIMER'. */
touch_pad_set_fsm_mode( TOUCH_FSM_MODE_TIMER );
/* Set reference voltage for charging/discharging */
/* For most usage scenarios, we recommend using the following combination: */
/* the high reference valtage will be 2.7V - 1V = 1.7V, The low reference voltage will be 0.5V. */
touch_pad_set_voltage( TOUCH_HVOLT_2V7, TOUCH_LVOLT_0V5, TOUCH_HVOLT_ATTEN_1V );
/* Init touch pad IO */
//tp_example_touch_pad_init();
touch_pad_config(TOUCH_PAD_NUM7, TOUCH_THRESH_NO_USE);
/* Initialize and start a software filter to detect slight change of capacitance.*/
touch_pad_filter_start( TOUCHPAD_FILTER_TOUCH_PERIOD );
/* Set thresh hold */
tp_example_set_thresholds();
/* Register touch interrupt ISR */
touch_pad_isr_register( tp_example_rtc_intr, NULL );
/* Variables */
static int show_message;
uint32_t change_mode = 0;
uint32_t filter_mode = 0;
for(;;)
{
if ( filter_mode == 0 )
{
/* interrupt mode, enable touch interrupt */
touch_pad_intr_enable();
if ( s_pad_activated == true)
{
printf("T7 activated!\n");
/* Wait a while for the pad being released */
vTaskDelay( pdMS_TO_TICKS( 200 ) );
/* Clear information on pad activation */
s_pad_activated = false;
/* Reset the counter triggering a message */
/* that application is running */
show_message = 1;
}
}
else
{
/* filter mode, disable touch interrupt */
touch_pad_intr_disable();
touch_pad_clear_status();
//for (int i = 0; i < TOUCH_PAD_MAX; i++) {
uint16_t value = 0;
touch_pad_read_filtered(7, &value);
if ( value < s_pad_init_val * TOUCH_THRESH_PERCENT / 100 )
{
printf("T7 activated!\n");
printf("Value: %d; Init val: %d\n",value,s_pad_init_val);
vTaskDelay( pdMS_TO_TICKS( 200 ) );
/* Reset the counter to stop changing mode. */
change_mode = 1;
show_message = 1;
}
}
vTaskDelay( pdMS_TO_TICKS( 10 ) );
/* If no pad is touched, every couple of seconds, show a message */
/* that application is running */
if ( show_message++ % 500 == 0 )
{
printf("Waiting for any pad being touched..\n");
}
/* Change mode if no pad is touched for a long time. */
/* We can compare the two different mode. */
if ( change_mode++ % 2000 == 0 )
{
filter_mode = !filter_mode;
printf("Change mode...%s", filter_mode == 0? "interrupt mode": "filter mode");
printf("\n");
}
}
}
/*
*
*/
static void pushButtonSD( void *pvParameters )
{
/* Configuration LED RGB */
gpio_config_t io_conf;
/* disable interrupt */
io_conf.intr_type = GPIO_PIN_INTR_DISABLE;
/* set as input mode */
io_conf.mode = GPIO_MODE_INPUT;
/* bit mask of the pins that you want to set,e.g.GPIO18/19 */
io_conf.pin_bit_mask = GPIO_INPUT_PIN_SEL;
/* configure GPIO with the given settings */
gpio_config( &io_conf );
/* Message */
printf("Initializing SD card\n");
printf("Using SPI peripheral\n");
sdmmc_host_t host = SDSPI_HOST_DEFAULT();
sdspi_slot_config_t slot_config = SDSPI_SLOT_CONFIG_DEFAULT();
slot_config.gpio_miso = PIN_NUM_MISO;
slot_config.gpio_mosi = PIN_NUM_MOSI;
slot_config.gpio_sck = PIN_NUM_CLK;
slot_config.gpio_cs = PIN_NUM_CS;
/* This initializes the slot without card detect (CD) and write protect (WP) signals. */
/* Modify slot_config.gpio_cd and slot_config.gpio_wp if your board has these signals. */
/* Options for mounting the filesystem. */
/* If format_if_mount_failed is set to true, SD card will be partitioned and */
/* formatted in case when mounting fails. */
esp_vfs_fat_sdmmc_mount_config_t mount_config = {
.format_if_mount_failed = false,
.max_files = 5,
.allocation_unit_size = 16 * 1024
};
/* Initialization Variables */
flag_memory = false;
for(;;)
{
if( 1 == gpio_get_level( GPIO_INPUT_PB_1 ) )
printf( "Task pushButtonSD: unpressed ...\n" );
else
printf( "Task pushButtonSD: pressed ...\n" );
if( 1 == gpio_get_level( GPIO_INPUT_CD ) ){
printf( "Task pushButtonSD: NO Memory Card ...\n" );
flag_memory = true;
}
else{
/* To avoid noise */
vTaskDelay( pdMS_TO_TICKS( 100 ) );
if( ( 0 == gpio_get_level( GPIO_INPUT_CD ) ) && ( true == flag_memory ) )
{
flag_memory = false;
printf( "Task pushButtonSD: Memory Card ...\n" );
/* Use settings defined above to initialize SD card and mount FAT filesystem. */
/* Note: esp_vfs_fat_sdmmc_mount is an all-in-one convenience function. */
/* Please check its source code and implement error recovery when developing */
/* production applications. */
sdmmc_card_t* card;
esp_err_t ret = esp_vfs_fat_sdmmc_mount("/sdcard", &host, &slot_config, &mount_config, &card);
if (ret != ESP_OK)
{
if (ret == ESP_FAIL)
{
printf("Failed to mount filesystem.\n");
printf("If you want the card to be formatted, set format_if_mount_failed = true.\n");
} else {
printf("Failed to initialize the card (%s).\n",esp_err_to_name(ret) );
printf("Make sure SD card lines have pull-up resistors in place.\n");
}
}
/* Card has been initialized, print its properties */
sdmmc_card_print_info( stdout, card );
/* Use POSIX and C standard library functions to work with files. */
/* First create a file. */
printf("Opening file...\n");
FILE* f = fopen("/sdcard/hello.txt", "w");
if (f == NULL) {
printf("Failed to open file for writing...\n");
}
fprintf(f, "Hello %s!\n", card->cid.name);
fclose(f);
printf("File written...\n");
// Check if destination file exists before renaming
struct stat st;
if ( stat("/sdcard/foo.txt", &st ) == 0 ) {
/* Delete it if it exists */
unlink("/sdcard/foo.txt");
}
/* Rename original file */
printf("Renaming file...\n");
if ( rename("/sdcard/hello.txt", "/sdcard/foo.txt") != 0){
printf("Rename failed...\n");
}
/* Open renamed file for reading */
printf("Reading file...\n");
f = fopen("/sdcard/foo.txt", "r");
if (f == NULL) {
printf("Failed to open file for reading...\n");
}
char line[64];
fgets( line, sizeof(line), f );
fclose(f);
/* strip newline */
char* pos = strchr(line, '\n');
if (pos) {
*pos = '\0';
}
printf("Read from file: '%s'", line);
/* All done, unmount partition and disable SDMMC or SPI peripheral */
esp_vfs_fat_sdmmc_unmount();
printf("Card unmounted...\n");
}
}
vTaskDelay( pdMS_TO_TICKS( 1000 ) );
}
}
No hay comentarios.:
Publicar un comentario