/** * Copyright (c) 2017-2018 Tara Keeling * * This software is released under the MIT License. * https://opensource.org/licenses/MIT */ #include #include #include #include #include #include #include #include "gds.h" #include "gds_err.h" #include "gds_private.h" #include "gds_default_if.h" static const int GDS_SPI_Command_Mode = 0; static const int GDS_SPI_Data_Mode = 1; static spi_host_device_t SPIHost; static int DCPin; static bool SPIDefaultWriteBytes( spi_device_handle_t SPIHandle, int WriteMode, const uint8_t* Data, size_t DataLength ); static bool SPIDefaultWriteCommand( struct GDS_Device* Device, uint8_t Command ); static bool SPIDefaultWriteData( struct GDS_Device* Device, const uint8_t* Data, size_t DataLength ); bool GDS_SPIInit( int SPI, int DC ) { SPIHost = SPI; DCPin = DC; return true; } bool GDS_SPIAttachDevice( struct GDS_Device* Device, int Width, int Height, int CSPin, int RSTPin, int BackLightPin, int Speed, int Mode ) { spi_device_interface_config_t SPIDeviceConfig = { }; spi_device_handle_t SPIDevice; NullCheck( Device, return false ); if (CSPin >= 0) { ESP_ERROR_CHECK_NONFATAL( gpio_set_direction( CSPin, GPIO_MODE_OUTPUT ), return false ); ESP_ERROR_CHECK_NONFATAL( gpio_set_level( CSPin, 0 ), return false ); } SPIDeviceConfig.clock_speed_hz = Speed > 0 ? Speed : SPI_MASTER_FREQ_8M; SPIDeviceConfig.spics_io_num = CSPin; SPIDeviceConfig.queue_size = 1; SPIDeviceConfig.mode = Mode; SPIDeviceConfig.flags = SPI_DEVICE_NO_DUMMY; if (Device->SPIParams) Device->SPIParams(SPIDeviceConfig.clock_speed_hz, &SPIDeviceConfig.mode, &SPIDeviceConfig.cs_ena_pretrans, &SPIDeviceConfig.cs_ena_posttrans); ESP_ERROR_CHECK_NONFATAL( spi_bus_add_device( SPIHost, &SPIDeviceConfig, &SPIDevice ), return false ); Device->WriteCommand = SPIDefaultWriteCommand; Device->WriteData = SPIDefaultWriteData; Device->SPIHandle = SPIDevice; Device->RSTPin = RSTPin; Device->CSPin = CSPin; Device->Backlight.Pin = BackLightPin; Device->IF = GDS_IF_SPI; Device->Width = Device->TextWidth = Width; Device->Height = Height; if ( RSTPin >= 0 ) { ESP_ERROR_CHECK_NONFATAL( gpio_set_direction( RSTPin, GPIO_MODE_OUTPUT ), return false ); ESP_ERROR_CHECK_NONFATAL( gpio_set_level( RSTPin, 0 ), return false ); GDS_Reset( Device ); } return GDS_Init( Device ); } static bool SPIDefaultWriteBytes( spi_device_handle_t SPIHandle, int WriteMode, const uint8_t* Data, size_t DataLength ) { spi_transaction_t SPITransaction = { }; NullCheck( SPIHandle, return false ); NullCheck( Data, return false ); if ( DataLength > 0 ) { gpio_set_level( DCPin, WriteMode ); SPITransaction.length = DataLength * 8; if (DataLength <= 4) { SPITransaction.flags = SPI_TRANS_USE_TXDATA; SPITransaction.tx_data[0] = *Data++; SPITransaction.tx_data[1] = *Data++; SPITransaction.tx_data[2] = *Data++; SPITransaction.tx_data[3] = *Data; } else { SPITransaction.tx_buffer = Data; } // only do polling as we don't have contention on SPI (otherwise DMA for transfers > 16 bytes) ESP_ERROR_CHECK_NONFATAL( spi_device_polling_transmit(SPIHandle, &SPITransaction), return false ); } return true; } static bool SPIDefaultWriteCommand( struct GDS_Device* Device, uint8_t Command ) { static uint8_t CommandByte = 0; NullCheck( Device, return false ); NullCheck( Device->SPIHandle, return false ); CommandByte = Command; return SPIDefaultWriteBytes( Device->SPIHandle, GDS_SPI_Command_Mode, &CommandByte, 1 ); } static bool SPIDefaultWriteData( struct GDS_Device* Device, const uint8_t* Data, size_t DataLength ) { NullCheck( Device, return false ); NullCheck( Device->SPIHandle, return false ); return SPIDefaultWriteBytes( Device->SPIHandle, GDS_SPI_Data_Mode, Data, DataLength ); }