Created
          May 20, 2025 16:21 
        
      - 
      
- 
        Save jef-sure/f5a4c72662b4f0ce9859d43eaa226346 to your computer and use it in GitHub Desktop. 
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
  | #include "spi_shiftout.h" | |
| #include "driver/gpio.h" | |
| #include "esp_log.h" | |
| #include <stdlib.h> | |
| #include <string.h> | |
| static const char *TAG = "spi_shiftout"; | |
| spi_shiftout_t *spi_shiftout_init(int32_t frequency, gpio_num_t data_pin, gpio_num_t clock_pin, gpio_num_t latch_pin, | |
| gpio_num_t output_enable_pin, spi_host_device_t host, uint8_t shift_out_length) | |
| { | |
| spi_shiftout_t *cfg = (spi_shiftout_t *)calloc(1, sizeof(spi_shiftout_t) + shift_out_length - 1); | |
| if (!cfg) { | |
| ESP_LOGE(TAG, "Failed to allocate memory for spi_shiftout_t"); | |
| return NULL; | |
| } | |
| cfg->latch_pin = latch_pin; | |
| cfg->output_enable_pin = output_enable_pin; | |
| cfg->output_enable_value = 255; // Default value for output enable | |
| cfg->shift_out_length = shift_out_length; | |
| cfg->ledc_channel = LEDC_CHANNEL_0; // or another available channel | |
| cfg->ledc_timer = LEDC_TIMER_0; // or another available timer | |
| if (output_enable_pin >= 0) { | |
| // Configure OE pin for PWM (LEDC) | |
| ledc_timer_config_t ledc_timer = { | |
| .speed_mode = LEDC_LOW_SPEED_MODE, // | |
| .timer_num = cfg->ledc_timer, // | |
| .duty_resolution = LEDC_TIMER_8_BIT, // | |
| .freq_hz = 8000, // TODO: test this value | |
| .clk_cfg = LEDC_AUTO_CLK // | |
| }; | |
| ledc_timer_config(&ledc_timer); | |
| ledc_channel_config_t ledc_channel = { | |
| .gpio_num = cfg->output_enable_pin, // | |
| .speed_mode = LEDC_LOW_SPEED_MODE, // | |
| .channel = cfg->ledc_channel, // | |
| .timer_sel = cfg->ledc_timer, // | |
| .duty = cfg->output_enable_value, // 100% duty (fully enabled) | |
| .hpoint = 0, // | |
| .flags.output_invert = 0 // | |
| }; | |
| ledc_channel_config(&ledc_channel); | |
| } | |
| // Configure the SPI bus | |
| spi_bus_config_t buscfg = { | |
| .miso_io_num = -1, // | |
| .mosi_io_num = data_pin, // | |
| .sclk_io_num = clock_pin, // | |
| .quadwp_io_num = -1, // | |
| .quadhd_io_num = -1, // | |
| .max_transfer_sz = shift_out_length * 8, // | |
| .flags = 0 // | |
| }; | |
| spi_device_interface_config_t devcfg = { | |
| .clock_speed_hz = frequency, // Clock out at 2 MHz | |
| .mode = 0, // SPI mode 0 | |
| .spics_io_num = -1, // CS pin | |
| .queue_size = 1, // | |
| .pre_cb = 0, // | |
| }; | |
| esp_err_t ret; | |
| // Initialize the SPI bus | |
| ret = spi_bus_initialize(host, &buscfg, SPI_DMA_CH_AUTO); | |
| ESP_ERROR_CHECK(ret); | |
| ret = spi_bus_add_device(host, &devcfg, &cfg->spi); | |
| ESP_ERROR_CHECK(ret); | |
| gpio_config_t latch_conf = { | |
| .pin_bit_mask = (1ULL << latch_pin), // | |
| .mode = GPIO_MODE_OUTPUT, // | |
| .pull_up_en = GPIO_PULLUP_ENABLE, // | |
| .pull_down_en = GPIO_PULLDOWN_DISABLE, // | |
| .intr_type = GPIO_INTR_DISABLE // | |
| }; | |
| gpio_config(&latch_conf); | |
| gpio_set_level(latch_pin, 1); | |
| return cfg; | |
| } | |
| void spi_shiftout_write(spi_shiftout_t *cfg, uint8_t oe_val) | |
| { | |
| esp_err_t ret; | |
| spi_transaction_t t; | |
| gpio_set_level(cfg->latch_pin, 0); | |
| memset(&t, 0, sizeof(t)); // Zero out the transaction | |
| t.length = 8 * cfg->shift_out_length; // Command is 8 bits | |
| t.tx_buffer = cfg->shift_out; // Data | |
| ret = spi_device_polling_transmit(cfg->spi, &t); // Transmit! | |
| gpio_set_level(cfg->latch_pin, 1); | |
| assert(ret == ESP_OK); // Should have had no issues. | |
| if (cfg->output_enable_pin >= 0 && oe_val != cfg->output_enable_value) { | |
| cfg->output_enable_value = oe_val; | |
| ledc_set_duty(LEDC_LOW_SPEED_MODE, cfg->ledc_channel, oe_val); | |
| ledc_update_duty(LEDC_LOW_SPEED_MODE, cfg->ledc_channel); | |
| } | |
| } | 
  
    Sign up for free
    to join this conversation on GitHub.
    Already have an account?
    Sign in to comment