Ejemplo FreeRTOS

/* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */
/*
 * 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