initial
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018, Alexey Dynda
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file ssd1306_hal/Print_internal.h SSD1306 Print class implementation
|
||||
*/
|
||||
|
||||
#ifndef _SSD1306_HAL_PRINT_INTERNAL_H_
|
||||
#define _SSD1306_HAL_PRINT_INTERNAL_H_
|
||||
|
||||
#if defined(ARDUINO) && !defined(ARDUINO_FAKE)
|
||||
|
||||
/* Include standard print class for Arduino environment */
|
||||
#include "Print.h"
|
||||
|
||||
#else
|
||||
|
||||
#include "ssd1306_hal/io.h"
|
||||
#include <stdio.h>
|
||||
|
||||
/** Implements own Print class for plain AVR and Linux environment */
|
||||
class Print
|
||||
{
|
||||
public:
|
||||
/** Constructor to create Print class object */
|
||||
Print() {}
|
||||
|
||||
/**
|
||||
* abstract function to be defined in inherited classes
|
||||
* @param ch char to print
|
||||
* @return returns number of printed symbols
|
||||
*/
|
||||
virtual size_t write(uint8_t ch) = 0;
|
||||
|
||||
/**
|
||||
* Prints string via write()
|
||||
* @param str string to print
|
||||
* @return returns number of printed symbols
|
||||
*/
|
||||
size_t print(const char* str)
|
||||
{
|
||||
size_t n = 0;
|
||||
while (*str)
|
||||
{
|
||||
n += write(*str);
|
||||
str++;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints number via write()
|
||||
* @param n integer to print
|
||||
* @return returns number of printed symbols
|
||||
*/
|
||||
size_t print(int n)
|
||||
{
|
||||
char a[10];
|
||||
snprintf(a, sizeof(a), "%i", n);
|
||||
return print( a );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints string via write() and goes to next line.
|
||||
* @param str string to print
|
||||
* @return returns number of printed symbols
|
||||
*/
|
||||
size_t println(const char* str)
|
||||
{
|
||||
size_t n = print(str);
|
||||
n += write('\n');
|
||||
return n;
|
||||
};
|
||||
|
||||
/**
|
||||
* Prints number via write() and goes to next line.
|
||||
* @param data integer to print
|
||||
* @return returns number of printed symbols
|
||||
*/
|
||||
size_t println(int data)
|
||||
{
|
||||
size_t n = print(data);
|
||||
n += write('\n');
|
||||
return n;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,14 @@
|
||||
# Hardware abstraction layer
|
||||
|
||||
This directory contain platform specific implementation of hardware abstraction layer.
|
||||
|
||||
* arduino dir: for all Arduino platforms (if you use Arduino IDE)
|
||||
* avr dir: for plain avr-gcc environment
|
||||
* esp dir: for plain esp8266/esp32 environment
|
||||
* linux dir: for linux platforms including raspberry pi
|
||||
* mingw dir: for running under windows
|
||||
* stm32 dir: for plain stm32 support (not implemented)
|
||||
* energia dir: for Energia platforms w/ MSP432P401R
|
||||
|
||||
Edit UserSettings.h header file, if you want to disable some parts of ssd1306 library to reduce memory consumption in your project
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018, Alexey Dynda
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
/**
|
||||
* @file UserSettings.h SSD1306 modules configuration.
|
||||
*/
|
||||
|
||||
#ifndef _USER_SETTINGS_H_
|
||||
#define _USER_SETTINGS_H_
|
||||
|
||||
/**
|
||||
* @defgroup SSD1306_LIBRARY_CONFIG CONFIG: ssd1306 library configuration
|
||||
* @{
|
||||
*
|
||||
* @brief Group of settings allowing to disable/enable library modules
|
||||
*
|
||||
* @details Arduino IDE (at least as for 1.8.2) has a lack library configuration functionality.
|
||||
* Some Arduino standard libraries are built the way, if you include them to the project,
|
||||
* but do not use any functions from the, they still eat RAM and Flash on you EVK board.
|
||||
* To avoid this, you need competely avoid including of such libraries. SSD1306 library
|
||||
* has a wide interfaces support for different platforms, and even if you don't use
|
||||
* SSD1306 communication via Arduino Wire/Spi/HardwareSerial libraries, those ones do
|
||||
* bad things with your sketch size.
|
||||
* To avoid this you can manually disable SSD1306 modules, you don't need in UserSettings.h
|
||||
* header file, and gain another 100-200 bytes of RAM and 300-500 bytes of Flash.
|
||||
*/
|
||||
|
||||
/* Comment out options below if you don't need support in the library, *
|
||||
* and want to reduce memory consumption. */
|
||||
|
||||
/** Define this macro if you need to enable software I2C module for compilation */
|
||||
#define CONFIG_SOFTWARE_I2C_ENABLE
|
||||
|
||||
/** Define this macro if you need to enable TWI I2C module for compilation */
|
||||
#define CONFIG_TWI_I2C_ENABLE
|
||||
|
||||
/** Define this macro if you need to enable AVR SPI module for compilation */
|
||||
#define CONFIG_AVR_SPI_ENABLE
|
||||
|
||||
/** Define this macro if you need to enable USI SPI module for compilation */
|
||||
#define CONFIG_USI_SPI_ENABLE
|
||||
|
||||
/** Define this macro if you need to enable AVR UART module for compilation */
|
||||
#define CONFIG_AVR_UART_ENABLE
|
||||
|
||||
/** Define this macro if you need to enable VGA module for compilation */
|
||||
#define CONFIG_VGA_ENABLE
|
||||
|
||||
/** Define this macro if you need to enable Adafruit GFX canvas support for compilation */
|
||||
#ifndef CONFIG_ADAFRUIT_GFX_ENABLE
|
||||
//#define CONFIG_ADAFRUIT_GFX_ENABLE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Define this macro if platform specific i2c interface is implemented in SSD1306 HAL.
|
||||
* If you use Arduino platform, this macro enables Arduino Wire library module for compilation.
|
||||
*/
|
||||
#define CONFIG_PLATFORM_I2C_ENABLE
|
||||
|
||||
/**
|
||||
* Define this macro if platform specific spi interface is implemented in SSD1306 HAL
|
||||
* If you use Arduino platform, this macro enables Arduino SPI library module for compilation.
|
||||
*/
|
||||
#define CONFIG_PLATFORM_SPI_ENABLE
|
||||
|
||||
/**
|
||||
* Defines, whenever ssd1306 library supports unicode.
|
||||
* Support of unicode increases RAM and Flasg memory consumption
|
||||
*/
|
||||
#define CONFIG_SSD1306_UNICODE_ENABLE
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,225 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018-2021, Alexey Dynda
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file hal/arduino/io.h SSD1306 ARDUINO IO communication functions
|
||||
*/
|
||||
|
||||
#ifndef _SSD1306_ARDUINO_IO_H_
|
||||
#define _SSD1306_ARDUINO_IO_H_
|
||||
|
||||
#if defined(ARDUINO_ARCH_STM32) // stm32duino support
|
||||
#include <Arduino.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#elif defined(ESP8266) || defined(ESP32) || defined(ESP31B) // esp arduino support
|
||||
#include <Arduino.h>
|
||||
#include <pgmspace.h>
|
||||
#else // AVR support
|
||||
#include <Arduino.h>
|
||||
#if !defined(ARDUINO_ARCH_SAMD) && defined(__AVR__)
|
||||
#include <avr/sleep.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include <avr/interrupt.h>
|
||||
#elif defined(ARDUINO_ARCH_SAMD)
|
||||
#include <api/deprecated-avr-comp/avr/pgmspace.h>
|
||||
#include <api/deprecated-avr-comp/avr/interrupt.h>
|
||||
#else
|
||||
#include <avr/pgmspace.h>
|
||||
#include <avr/interrupt.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(ARDUINO_ARCH_STM32)
|
||||
/** The macro is defined when i2c Wire library is available */
|
||||
#define CONFIG_PLATFORM_I2C_AVAILABLE
|
||||
/** The macro is defined when Wire library speed can be configured */
|
||||
#define SSD1306_WIRE_CLOCK_CONFIGURABLE
|
||||
/** The macro is defined when SPI library is available */
|
||||
#define CONFIG_PLATFORM_SPI_AVAILABLE
|
||||
/** The macro is defined when STM32 i2c implementation is available */
|
||||
#define CONFIG_STM32_I2C_AVAILABLE
|
||||
|
||||
#elif defined(ARDUINO_AVR_DIGISPARK) || defined(ARDUINO_AVR_DIGISPARKPRO)
|
||||
/** The macro is defined when i2c Wire library is available */
|
||||
#define CONFIG_PLATFORM_I2C_AVAILABLE
|
||||
#if defined(ARDUINO_AVR_DIGISPARKPRO)
|
||||
/** The macro is defined when SPI library is available */
|
||||
#define CONFIG_PLATFORM_SPI_AVAILABLE
|
||||
#else
|
||||
/** The macro is defined when software i2c implementation is available */
|
||||
#define CONFIG_SOFTWARE_I2C_AVAILABLE
|
||||
/* Define lcdint as smallest types to reduce memo usage on tiny controllers. *
|
||||
* Remember, that this can cause issues with large lcd displays, i.e. 320x240*/
|
||||
#define LCDINT_TYPES_DEFINED
|
||||
typedef int8_t lcdint_t;
|
||||
typedef uint8_t lcduint_t;
|
||||
#endif
|
||||
|
||||
#elif defined(ARDUINO_AVR_ATTINYX5) || defined(ARDUINO_AVR_ATTINYX4)
|
||||
|
||||
/** The macro is defined when software i2c implementation is available */
|
||||
#define CONFIG_SOFTWARE_I2C_AVAILABLE
|
||||
/** The macro is defined when i2c Wire library is available */
|
||||
#define CONFIG_PLATFORM_I2C_AVAILABLE
|
||||
/** The macro is defined when USI module is available for use */
|
||||
#define CONFIG_USI_SPI_AVAILABLE
|
||||
/** The macro is defined when SPI library is available */
|
||||
#define CONFIG_PLATFORM_SPI_AVAILABLE
|
||||
/** Define lcdint as smallest types to reduce memo usage on tiny controllers. *
|
||||
* Remember, that this can cause issues with large lcd displays, i.e. 320x240*/
|
||||
#define LCDINT_TYPES_DEFINED
|
||||
/** This is for Attiny controllers */
|
||||
typedef int8_t lcdint_t;
|
||||
/** This is for Attiny controllers */
|
||||
typedef uint8_t lcduint_t;
|
||||
/** The macro is defined when micro controller doesn't support multiplication operation */
|
||||
#define CONFIG_MULTIPLICATION_NOT_SUPPORTED
|
||||
|
||||
#elif defined(__AVR_ATtinyxy4__) || defined(__AVR_ATtinyxy2__) || defined(__AVR_ATtinyxy6__) || defined(__AVR_ATtinyxy7__)
|
||||
/** The macro is defined when i2c Wire library is available */
|
||||
#define CONFIG_PLATFORM_I2C_AVAILABLE
|
||||
/** The macro is defined when Wire library speed can be configured */
|
||||
// Note: Might work for faster draw. But it does brick some devices that can't run at these speeds.
|
||||
// Leaving it off for now
|
||||
//#define SSD1306_WIRE_CLOCK_CONFIGURABLE
|
||||
/** The macro is defined when SPI library is available */
|
||||
#define CONFIG_PLATFORM_SPI_AVAILABLE
|
||||
/** Define lcdint as smallest types to reduce memo usage on tiny controllers. *
|
||||
* Remember, that this can cause issues with large lcd displays, i.e. 320x240*/
|
||||
#define LCDINT_TYPES_DEFINED
|
||||
/** This is for Attiny controllers */
|
||||
typedef int8_t lcdint_t;
|
||||
/** This is for Attiny controllers */
|
||||
typedef uint8_t lcduint_t;
|
||||
/** The macro is defined when micro controller doesn't support multiplication operation */
|
||||
//#define CONFIG_MULTIPLICATION_NOT_SUPPORTED
|
||||
|
||||
|
||||
#elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) || \
|
||||
defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
|
||||
|
||||
/** The macro is defined when software i2c implementation is available */
|
||||
#define CONFIG_SOFTWARE_I2C_AVAILABLE
|
||||
/** The macro is defined when USI module is available for use */
|
||||
#define CONFIG_USI_SPI_AVAILABLE
|
||||
/** Define lcdint as smallest types to reduce memo usage on tiny controllers. *
|
||||
* Remember, that this can cause issues with large lcd displays, i.e. 320x240*/
|
||||
#define LCDINT_TYPES_DEFINED
|
||||
/** This is for Attiny controllers */
|
||||
typedef int8_t lcdint_t;
|
||||
/** This is for Attiny controllers */
|
||||
typedef uint8_t lcduint_t;
|
||||
/** The macro is defined when micro controller doesn't support multiplication operation */
|
||||
#define CONFIG_MULTIPLICATION_NOT_SUPPORTED
|
||||
|
||||
#elif defined(ESP8266) || defined(ESP32) || defined(ESP31B) || \
|
||||
defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_SAM)
|
||||
/* SW implementation of i2c isn't supported on ESP platforms */
|
||||
/** The macro is defined when i2c Wire library is available */
|
||||
#define CONFIG_PLATFORM_I2C_AVAILABLE
|
||||
/** The macro is defined when Wire library speed can be configured */
|
||||
#define SSD1306_WIRE_CLOCK_CONFIGURABLE
|
||||
/** The macro is defined when SPI library is available */
|
||||
#define CONFIG_PLATFORM_SPI_AVAILABLE
|
||||
#if defined(ESP32)
|
||||
/** The macro is defined when composite audio support is available */
|
||||
#define CONFIG_VGA_AVAILABLE
|
||||
#endif
|
||||
|
||||
#elif defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328PB__)
|
||||
/** The macro is defined when i2c Wire library is available */
|
||||
#define CONFIG_SOFTWARE_I2C_AVAILABLE
|
||||
/** The macro is defined when i2c Wire library is available */
|
||||
#define CONFIG_PLATFORM_I2C_AVAILABLE
|
||||
/** The macro is defined when Wire library speed can be configured */
|
||||
#define SSD1306_WIRE_CLOCK_CONFIGURABLE
|
||||
/** The macro is defined when TWI module is available (ATTINY) */
|
||||
#define CONFIG_TWI_I2C_AVAILABLE
|
||||
/** The macro is defined when SPI library is available */
|
||||
#define CONFIG_PLATFORM_SPI_AVAILABLE
|
||||
/** The macro is defined when SPI module is available (ATMEGA) */
|
||||
#define CONFIG_AVR_SPI_AVAILABLE
|
||||
/** The macro is defined when UART module is available */
|
||||
#define CONFIG_AVR_UART_AVAILABLE
|
||||
/** The macro is defined when VGA monitor control is available directly from controller */
|
||||
#define CONFIG_VGA_AVAILABLE
|
||||
#if defined(__AVR_ATmega328PB__) && !defined(WIRE_INTERFACES_COUNT)
|
||||
#define WIRE_INTERFACES_COUNT 2
|
||||
#endif
|
||||
|
||||
#elif defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1280__)
|
||||
/** The macro is defined when i2c Wire library is available */
|
||||
#define CONFIG_SOFTWARE_I2C_AVAILABLE
|
||||
/** The macro is defined when i2c Wire library is available */
|
||||
#define CONFIG_PLATFORM_I2C_AVAILABLE
|
||||
/** The macro is defined when Wire library speed can be configured */
|
||||
#define SSD1306_WIRE_CLOCK_CONFIGURABLE
|
||||
/** The macro is defined when TWI module is available (ATTINY) */
|
||||
#define CONFIG_TWI_I2C_AVAILABLE
|
||||
/** The macro is defined when SPI library is available */
|
||||
#define CONFIG_PLATFORM_SPI_AVAILABLE
|
||||
// Disable internal AVR SPI implementation for ATMEGA 2560 since,
|
||||
// it doesn't work for now
|
||||
// #define CONFIG_AVR_SPI_AVAILABLE
|
||||
|
||||
#elif defined(NRF52) || defined(NRF5)
|
||||
/** The macro is defined when i2c Wire library is available */
|
||||
#define CONFIG_PLATFORM_I2C_AVAILABLE
|
||||
/** The macro is defined when Wire library speed can be configured */
|
||||
#define SSD1306_WIRE_CLOCK_CONFIGURABLE
|
||||
/** The macro is defined when SPI library is available */
|
||||
#define CONFIG_PLATFORM_SPI_AVAILABLE
|
||||
|
||||
#elif defined(__AVR_ATmega4808__) || defined(__AVR_ATmega3208__) || defined(__AVR_ATmega1608__)
|
||||
|
||||
/** The macro is defined when i2c Wire library is available */
|
||||
#define CONFIG_PLATFORM_I2C_AVAILABLE
|
||||
/** The macro is defined when Wire library speed can be configured */
|
||||
#define SSD1306_WIRE_CLOCK_CONFIGURABLE
|
||||
/** The macro is defined when SPI library is available */
|
||||
#define CONFIG_PLATFORM_SPI_AVAILABLE
|
||||
|
||||
#else
|
||||
/** The macro is defined when i2c Wire library is available */
|
||||
#define CONFIG_SOFTWARE_I2C_AVAILABLE
|
||||
/** The macro is defined when i2c Wire library is available */
|
||||
#define CONFIG_PLATFORM_I2C_AVAILABLE
|
||||
/** The macro is defined when Wire library speed can be configured */
|
||||
#define SSD1306_WIRE_CLOCK_CONFIGURABLE
|
||||
/** The macro is defined when TWI module is available (ATTINY) */
|
||||
#define CONFIG_TWI_I2C_AVAILABLE
|
||||
/** The macro is defined when SPI library is available */
|
||||
#define CONFIG_PLATFORM_SPI_AVAILABLE
|
||||
/** The macro is defined when SPI module is available (ATMEGA) */
|
||||
#define CONFIG_AVR_SPI_AVAILABLE
|
||||
#endif
|
||||
|
||||
//#ifdef CONFIG_PLATFORM_I2C_AVAILABLE
|
||||
//#ifdef __cplusplus
|
||||
//#include <Wire.h>
|
||||
//#endif
|
||||
//#endif
|
||||
|
||||
#endif // _SSD1306_ARDUINO_IO_H_
|
||||
|
||||
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2016-2021, Alexey Dynda
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "ssd1306_hal/io.h"
|
||||
|
||||
#include "intf/ssd1306_interface.h"
|
||||
#include "intf/i2c/ssd1306_i2c.h"
|
||||
#include "intf/spi/ssd1306_spi.h"
|
||||
#include "lcd/lcd_common.h"
|
||||
|
||||
#if defined(ARDUINO) && !defined(ENERGIA)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// ARDUINO I2C IMPLEMENTATION
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(CONFIG_PLATFORM_I2C_AVAILABLE) && \
|
||||
defined(CONFIG_PLATFORM_I2C_ENABLE)
|
||||
|
||||
#include <Wire.h>
|
||||
#if defined( WIRE_INTERFACES_COUNT ) && WIRE_INTERFACES_COUNT > 1
|
||||
#include <Wire1.h>
|
||||
#endif
|
||||
|
||||
static uint8_t s_bytesWritten = 0;
|
||||
static uint8_t s_sa = SSD1306_SA;
|
||||
static TwoWire *s_i2c = nullptr;
|
||||
|
||||
static void ssd1306_i2cStart_Wire(void)
|
||||
{
|
||||
s_i2c->beginTransmission(s_sa);
|
||||
s_bytesWritten = 0;
|
||||
}
|
||||
|
||||
static void ssd1306_i2cStop_Wire(void)
|
||||
{
|
||||
s_i2c->endTransmission();
|
||||
}
|
||||
|
||||
/**
|
||||
* Inputs: SCL is LOW, SDA is has no meaning
|
||||
* Outputs: SCL is LOW
|
||||
*/
|
||||
static void ssd1306_i2cSendByte_Wire(uint8_t data)
|
||||
{
|
||||
// Do not write too many bytes for standard Wire.h. It may become broken
|
||||
#if defined(ESP32) || defined(ESP31B)
|
||||
if (s_bytesWritten >= (I2C_BUFFER_LENGTH >> 4))
|
||||
#elif defined(ARDUINO_ARCH_SAMD)
|
||||
if (s_bytesWritten >= 64)
|
||||
#elif defined(BUFFER_LENGTH)
|
||||
if (s_bytesWritten >= (BUFFER_LENGTH - 2))
|
||||
#elif defined(SERIAL_BUFFER_LENGTH)
|
||||
if (s_bytesWritten >= (SERIAL_BUFFER_LENGTH - 2))
|
||||
#elif defined(USI_BUF_SIZE)
|
||||
if (s_bytesWritten >= (USI_BUF_SIZE -2))
|
||||
#else
|
||||
if ( s_i2c->write(data) != 0 )
|
||||
{
|
||||
s_bytesWritten++;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
{
|
||||
ssd1306_i2cStop_Wire();
|
||||
ssd1306_i2cStart_Wire();
|
||||
ssd1306_i2cSendByte_Wire(0x40);
|
||||
/* Commands never require many bytes. Thus assume that user tries to send data */
|
||||
}
|
||||
s_i2c->write(data);
|
||||
s_bytesWritten++;
|
||||
}
|
||||
|
||||
static void ssd1306_i2cSendBytes_Wire(const uint8_t *buffer, uint16_t size)
|
||||
{
|
||||
while (size--)
|
||||
{
|
||||
ssd1306_i2cSendByte_Wire(*buffer);
|
||||
buffer++;
|
||||
}
|
||||
}
|
||||
|
||||
static void ssd1306_i2cClose_Wire()
|
||||
{
|
||||
}
|
||||
|
||||
void ssd1306_platform_i2cInit(int8_t busId, uint8_t addr, ssd1306_platform_i2cConfig_t * cfg)
|
||||
{
|
||||
#if defined(ESP8266) || defined(ESP32) || defined(ESP31B)
|
||||
if ((cfg->scl >= 0) && (cfg->sda >=0))
|
||||
{
|
||||
s_i2c = &Wire;
|
||||
s_i2c->begin(cfg->sda, cfg->scl);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
#if !defined( WIRE_INTERFACES_COUNT )
|
||||
s_i2c = &Wire;
|
||||
#elif WIRE_INTERFACES_COUNT < 2
|
||||
s_i2c = &Wire;
|
||||
#elif WIRE_INTERFACES_COUNT < 3
|
||||
if ( busId == 0 )
|
||||
{
|
||||
s_i2c = &Wire;
|
||||
}
|
||||
else
|
||||
{
|
||||
s_i2c = &Wire1;
|
||||
}
|
||||
#endif
|
||||
s_i2c->begin();
|
||||
}
|
||||
#ifdef SSD1306_WIRE_CLOCK_CONFIGURABLE
|
||||
s_i2c->setClock(400000);
|
||||
#endif
|
||||
|
||||
if (addr) s_sa = addr;
|
||||
ssd1306_intf.spi = 0;
|
||||
ssd1306_intf.start = ssd1306_i2cStart_Wire;
|
||||
ssd1306_intf.stop = ssd1306_i2cStop_Wire;
|
||||
ssd1306_intf.send = ssd1306_i2cSendByte_Wire;
|
||||
ssd1306_intf.send_buffer = ssd1306_i2cSendBytes_Wire;
|
||||
ssd1306_intf.close = ssd1306_i2cClose_Wire;
|
||||
}
|
||||
|
||||
#endif // CONFIG_PLATFORM_I2C_AVAILABLE
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// ARDUINO SPI IMPLEMENTATION
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
#if defined(CONFIG_PLATFORM_SPI_AVAILABLE) && defined(CONFIG_PLATFORM_SPI_ENABLE)
|
||||
|
||||
/* STANDARD branch */
|
||||
#include <SPI.h>
|
||||
|
||||
static void ssd1306_spiClose_hw()
|
||||
{
|
||||
}
|
||||
|
||||
static void ssd1306_spiStart_hw()
|
||||
{
|
||||
/* anyway, oled ssd1331 cannot work faster, clock cycle should be > 150ns: *
|
||||
* 1s / 150ns ~ 6.7MHz */
|
||||
SPI.beginTransaction(SPISettings(s_ssd1306_spi_clock, MSBFIRST, SPI_MODE0));
|
||||
if (s_ssd1306_cs >= 0)
|
||||
{
|
||||
digitalWrite(s_ssd1306_cs,LOW);
|
||||
}
|
||||
}
|
||||
|
||||
static void ssd1306_spiStop_hw()
|
||||
{
|
||||
if (ssd1306_lcd.type == LCD_TYPE_PCD8544)
|
||||
{
|
||||
digitalWrite(s_ssd1306_dc, LOW);
|
||||
SPI.transfer( 0x00 ); // Send NOP command to allow last data byte to pass (bug in PCD8544?)
|
||||
// ssd1306 E3h is NOP command
|
||||
}
|
||||
if (s_ssd1306_cs >= 0)
|
||||
{
|
||||
digitalWrite(s_ssd1306_cs, HIGH);
|
||||
}
|
||||
SPI.endTransaction();
|
||||
}
|
||||
|
||||
static void ssd1306_spiSendByte_hw(uint8_t data)
|
||||
{
|
||||
SPI.transfer(data);
|
||||
}
|
||||
|
||||
static void ssd1306_spiSendBytes_hw(const uint8_t *buffer, uint16_t size)
|
||||
{
|
||||
/* Do not use SPI.transfer(buffer, size)! this method corrupts buffer content */
|
||||
while (size--)
|
||||
{
|
||||
SPI.transfer(*buffer);
|
||||
buffer++;
|
||||
};
|
||||
}
|
||||
|
||||
void ssd1306_platform_spiInit(int8_t busId, int8_t cesPin, int8_t dcPin)
|
||||
{
|
||||
if (cesPin >=0) pinMode(cesPin, OUTPUT);
|
||||
if (dcPin >= 0) pinMode(dcPin, OUTPUT);
|
||||
if (cesPin) s_ssd1306_cs = cesPin;
|
||||
if (dcPin) s_ssd1306_dc = dcPin;
|
||||
SPI.begin();
|
||||
ssd1306_intf.spi = 1;
|
||||
ssd1306_intf.start = ssd1306_spiStart_hw;
|
||||
ssd1306_intf.stop = ssd1306_spiStop_hw;
|
||||
ssd1306_intf.send = ssd1306_spiSendByte_hw;
|
||||
ssd1306_intf.send_buffer = ssd1306_spiSendBytes_hw;
|
||||
ssd1306_intf.close = ssd1306_spiClose_hw;
|
||||
}
|
||||
|
||||
#endif // CONFIG_PLATFORM_SPI_AVAILABLE
|
||||
|
||||
#endif // ARDUINO
|
||||
@@ -0,0 +1,13 @@
|
||||
#ifndef _ARDUINO_H_
|
||||
#define _ARDUINO_H_
|
||||
|
||||
#define ARDUINO_FAKE
|
||||
#include "ssd1306_hal/avr/io.h"
|
||||
#include "ssd1306_hal/Print_internal.h"
|
||||
|
||||
#ifndef boolean
|
||||
typedef uint8_t boolean;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
#ifndef _PRINT_H_
|
||||
#define _PRINT_H_
|
||||
|
||||
#include "ssd1306_hal/io.h"
|
||||
#include "ssd1306_hal/Print_internal.h"
|
||||
|
||||
#define __FlashStringHelper char
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018-2019, Alexey Dynda
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file ssd1306_hal/avr/io.h SSD1306 AVR IO communication functions
|
||||
*/
|
||||
|
||||
#ifndef _SSD1306_AVR_IO_H_
|
||||
#define _SSD1306_AVR_IO_H_
|
||||
|
||||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include <avr/sleep.h>
|
||||
#include <avr/eeprom.h>
|
||||
#include <util/delay.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define LOW 0
|
||||
#define HIGH 1
|
||||
#define INPUT 0
|
||||
#define OUTPUT 1
|
||||
|
||||
#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) || \
|
||||
defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
|
||||
/** The macro is defined when software i2c implementation is available */
|
||||
#define CONFIG_SOFTWARE_I2C_AVAILABLE
|
||||
/** The macro is defined when USI module is available for use */
|
||||
#define CONFIG_USI_SPI_AVAILABLE
|
||||
/* Define lcdint as smallest types to reduce memo usage on tiny controllers. *
|
||||
* Remember, that this can cause issues with large lcd displays, i.e. 320x240*/
|
||||
#define LCDINT_TYPES_DEFINED
|
||||
typedef int8_t lcdint_t;
|
||||
typedef uint8_t lcduint_t;
|
||||
/** The macro is defined when micro controller doesn't support multiplication operation */
|
||||
#define CONFIG_MULTIPLICATION_NOT_SUPPORTED
|
||||
#elif defined(__AVR_ATmega328P__)
|
||||
/** The macro is defined when software i2c implementation is available */
|
||||
#define CONFIG_SOFTWARE_I2C_AVAILABLE
|
||||
/** The macro is defined when TWI module is available */
|
||||
#define CONFIG_TWI_I2C_AVAILABLE
|
||||
/** The macro is defined when SPI module is available */
|
||||
#define CONFIG_AVR_SPI_AVAILABLE
|
||||
/** The macro is defined when UART module is available */
|
||||
#define CONFIG_AVR_UART_AVAILABLE
|
||||
/** The macro is defined when VGA monitor control is available directly from controller */
|
||||
#define CONFIG_VGA_AVAILABLE
|
||||
|
||||
#elif defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1280__)
|
||||
/** The macro is defined when i2c Wire library is available */
|
||||
#define CONFIG_SOFTWARE_I2C_AVAILABLE
|
||||
/** The macro is defined when TWI module is available (ATTINY) */
|
||||
#define CONFIG_TWI_I2C_AVAILABLE
|
||||
/** The macro is defined when SPI module is available */
|
||||
#define CONFIG_AVR_SPI_AVAILABLE
|
||||
|
||||
#else
|
||||
/** The macro is defined when software i2c implementation is available */
|
||||
#define CONFIG_SOFTWARE_I2C_AVAILABLE
|
||||
/** The macro is defined when TWI module is available */
|
||||
#define CONFIG_TWI_I2C_AVAILABLE
|
||||
/** The macro is defined when SPI module is available */
|
||||
#define CONFIG_AVR_SPI_AVAILABLE
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// not implemented functions for plain AVR
|
||||
static inline int digitalRead(int pin) { return LOW; };
|
||||
static inline int analogRead(int pin) { return 0; };
|
||||
static inline uint32_t millis() { return 0; };
|
||||
static inline void randomSeed(int seed) { };
|
||||
static inline void attachInterrupt(int pin, void (*interrupt)(), int level) { };
|
||||
|
||||
// implemented functions for plain AVR
|
||||
void delay(unsigned long ms);
|
||||
#define delayMicroseconds(us) _delay_us(us)
|
||||
|
||||
void digitalWrite(int pin, int level);
|
||||
void pinMode(int pin, int mode);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
static inline int random(int max) { return 0; };
|
||||
static inline int random(int min, int max) { return 0; };
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018, Alexey Dynda
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "ssd1306_hal/io.h"
|
||||
|
||||
#if defined(__AVR__) && !defined(ARDUINO)
|
||||
|
||||
void delay(unsigned long ms)
|
||||
{
|
||||
while (ms--)
|
||||
{
|
||||
_delay_ms(1);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
|
||||
#define G0_DIR DDRB
|
||||
#define G0_PORT PORTB
|
||||
#define G1_DIR DDRB
|
||||
#define G1_PORT PORTB
|
||||
#define G2_DIR DDRB
|
||||
#define G2_PORT PORTB
|
||||
#elif defined(__AVR_ATmega328P__)
|
||||
#define G0_DIR DDRD
|
||||
#define G0_PORT PORTD
|
||||
#define G1_DIR DDRB
|
||||
#define G1_PORT PORTB
|
||||
#define G2_DIR DDRC
|
||||
#define G2_PORT PORTC
|
||||
#else
|
||||
static uint8_t s_stub;
|
||||
#define G0_DIR s_stub
|
||||
#define G0_PORT s_stub
|
||||
#define G1_DIR s_stub
|
||||
#define G1_PORT s_stub
|
||||
#define G2_DIR s_stub
|
||||
#define G2_PORT s_stub
|
||||
#endif
|
||||
|
||||
void digitalWrite(int pin, int level)
|
||||
{
|
||||
uint8_t mask = (1<<(pin & 0x7));
|
||||
if (pin<8)
|
||||
{
|
||||
if (level == HIGH) G0_PORT |= mask; else G0_PORT &= ~mask;
|
||||
}
|
||||
else if (pin<16)
|
||||
{
|
||||
if (level == HIGH) G1_PORT |= mask; else G1_PORT &= ~mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (level == HIGH) G2_PORT |= mask; else G2_PORT &= ~mask;
|
||||
}
|
||||
}
|
||||
|
||||
void pinMode(int pin, int mode)
|
||||
{
|
||||
uint8_t mask = (1<<(pin & 0x7));
|
||||
if (pin<8)
|
||||
{
|
||||
if (mode == OUTPUT) G0_DIR |= mask; else G0_DIR &= ~mask;
|
||||
}
|
||||
else if (pin<16)
|
||||
{
|
||||
if (mode == OUTPUT) G1_DIR |= mask; else G1_DIR &= ~mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mode == OUTPUT) G2_DIR |= mask; else G2_DIR &= ~mask;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018, Alexey Dynda
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file ssd1306_hal/energia/io.h Energia IO functions abstraction
|
||||
*/
|
||||
|
||||
#ifndef _SSD1306_ENERGIA_IO_H_
|
||||
#define _SSD1306_ENERGIA_IO_H_
|
||||
|
||||
//========================== I. Create directory for your platform ========
|
||||
/* 1. Copy content of this folder to src/ssd1306_hal/<your_platform>/ folder */
|
||||
/* 2. Replace YOUR_PLATFORM in these files with the one, you would like to use */
|
||||
/* 3. Add #include "<your_platform>/io.h" to src/ssd1306_hal/io.h file */
|
||||
/* (remember to add required #elif defined(X) lines) */
|
||||
/* 4. Add platform.c file to SOURCES list in src/Makefile.src */
|
||||
/* 5. Implement functions below and functions in platform.c file */
|
||||
|
||||
#define SSD1306_ENERGIA_PLATFORM
|
||||
//========================== I. Include libraries =========================
|
||||
/* 1. Include all required headers, specific for your platform here */
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "Energia.h"
|
||||
#include <avr/pgmspace.h>
|
||||
#include <avr/interrupt.h>
|
||||
/* If your platform already has these definitions, comment out lines below */
|
||||
// #define LOW 0
|
||||
// #define HIGH 1
|
||||
// #define INPUT 0
|
||||
// #define OUTPUT 1
|
||||
|
||||
/* Progmem attribute for data, located in Flash */
|
||||
#define PROGMEM
|
||||
|
||||
//========================== II. Define options ===========================
|
||||
/* 2. Uncomment all options, you have support for on your platform *
|
||||
* Remember that you will need to implement low level intf/i2c or *
|
||||
* intf/spi layers for your platform */
|
||||
|
||||
//#define CONFIG_SOFTWARE_I2C_AVAILABLE
|
||||
//#define CONFIG_TWI_I2C_AVAILABLE
|
||||
//#define CONFIG_AVR_SPI_AVAILABLE
|
||||
//#define CONFIG_AVR_UART_AVAILABLE
|
||||
//#define CONFIG_VGA_AVAILABLE
|
||||
#define CONFIG_PLATFORM_I2C_AVAILABLE
|
||||
#define CONFIG_PLATFORM_SPI_AVAILABLE
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//========================== III. Implement functions =====================
|
||||
/* Implement functions below the way you like. You can make them non-static
|
||||
* and implement the functions in platform.c file
|
||||
*/
|
||||
// !!! MANDATORY. The library will not work without these functions !!!
|
||||
// static inline int digitalRead(int pin) // digitalRead()
|
||||
// {
|
||||
// return LOW;
|
||||
// }
|
||||
|
||||
// static inline void digitalWrite(int pin, int level) // digitalWrite()
|
||||
// {
|
||||
// }
|
||||
|
||||
// static inline void pinMode(int pin, int mode) // pinMode()
|
||||
// {
|
||||
// }
|
||||
|
||||
// static inline int analogRead(int pin) // analogRead()
|
||||
// {
|
||||
// return 0;
|
||||
// }
|
||||
|
||||
// static inline uint32_t millis(void) // millis()
|
||||
// {
|
||||
// return 0;
|
||||
// }
|
||||
|
||||
// static inline uint32_t micros(void) // micros()
|
||||
// {
|
||||
// return 0;
|
||||
// };
|
||||
|
||||
// static inline void delay(uint32_t ms) // delay()
|
||||
// {
|
||||
// }
|
||||
|
||||
// static inline void delayMicroseconds(uint32_t us) // delayMicroseconds()
|
||||
// {
|
||||
// }
|
||||
|
||||
// !!! OPTIONAL !!!
|
||||
//static inline void randomSeed(int seed) // randomSeed() - can be skipped
|
||||
//{
|
||||
//}
|
||||
//
|
||||
//static inline void attachInterrupt(int pin, void (*interrupt)(), int level) // attachInterrupt() - can be skipped
|
||||
//{
|
||||
//}
|
||||
//
|
||||
//static inline uint8_t pgm_read_byte(const void *ptr) // pgm_read_byte() - can be left as is
|
||||
//{
|
||||
// return *((const uint8_t *)ptr);
|
||||
//}
|
||||
//
|
||||
//static inline uint16_t eeprom_read_word(const void *ptr) // eeprom_read_word() - can be skipped
|
||||
//{
|
||||
// return 0;
|
||||
//}
|
||||
//
|
||||
//static inline void eeprom_write_word(const void *ptr, uint16_t val) // eeprom_write_word() - can be skipped
|
||||
//{
|
||||
//}
|
||||
|
||||
// static inline char *utoa(unsigned int num, char *str, int radix) // util utoa() - can be skipped
|
||||
// {
|
||||
// *str = '\0';
|
||||
// return str;
|
||||
//}
|
||||
|
||||
|
||||
// !!! PLATFORM I2C IMPLEMENTATION OPTIONAL !!!
|
||||
// #if defined(CONFIG_PLATFORM_I2C_AVAILABLE) && defined(CONFIG_PLATFORM_I2C_ENABLE)
|
||||
// void ssd1306_platform_i2cInit(int8_t busId, uint8_t addr, ssd1306_platform_i2cConfig_t * cfg);
|
||||
// #endif
|
||||
|
||||
|
||||
// !!! PLATFORM SPI IMPLEMENTATION OPTIONAL !!!
|
||||
//#if defined(CONFIG_PLATFORM_SPI_AVAILABLE) && defined(CONFIG_PLATFORM_SPI_ENABLE)
|
||||
//void ssd1306_platform_spiInit(uint8_t busId,
|
||||
// uint8_t cesPin,
|
||||
// uint8_t dcPin);
|
||||
//#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
static inline int random(int max) // random(n) - can be skipped if you don't use it
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int random(int min, int max) // random(a,b) - can be skipped if you don't use it
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018, Alexey Dynda
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "ssd1306_hal/io.h"
|
||||
|
||||
#if defined(SSD1306_ENERGIA_PLATFORM)
|
||||
|
||||
#include "intf/ssd1306_interface.h"
|
||||
#include <Wire.h> // Energia I2C implementation (Arduino-like)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
#if defined(CONFIG_PLATFORM_I2C_AVAILABLE) && defined(CONFIG_PLATFORM_I2C_ENABLE)
|
||||
static uint8_t s_bytesWritten = 0;
|
||||
static uint8_t s_i2c_addr = 0x3C;
|
||||
static TwoWire *s_i2c = nullptr;
|
||||
|
||||
static void platform_i2c_start(void)
|
||||
{
|
||||
s_i2c->beginTransmission(s_i2c_addr);
|
||||
s_bytesWritten = 0;
|
||||
}
|
||||
|
||||
static void platform_i2c_stop(void)
|
||||
{
|
||||
s_i2c->endTransmission();
|
||||
}
|
||||
|
||||
static void platform_i2c_send(uint8_t data)
|
||||
{
|
||||
// Do not write too many bytes for standard Wire.h. It may become broken (Arduino)
|
||||
if (s_bytesWritten >= (BUFFER_LENGTH - 2))
|
||||
{
|
||||
platform_i2c_stop();
|
||||
platform_i2c_start();
|
||||
platform_i2c_send(0x40);
|
||||
/* Commands never require many bytes. Thus assume that user tries to send data (Arduino) */
|
||||
}
|
||||
s_i2c->write(data);
|
||||
s_bytesWritten++;
|
||||
}
|
||||
|
||||
static void platform_i2c_close(void)
|
||||
{
|
||||
// ... free all i2c resources here
|
||||
}
|
||||
|
||||
static void platform_i2c_send_buffer(const uint8_t *data, uint16_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
platform_i2c_send(*data);
|
||||
data++;
|
||||
}
|
||||
}
|
||||
|
||||
void ssd1306_platform_i2cInit(int8_t busId, uint8_t addr, ssd1306_platform_i2cConfig_t * cfg)
|
||||
{
|
||||
s_i2c = &Wire;
|
||||
s_i2c->begin();
|
||||
|
||||
if (addr) s_i2c_addr = addr;
|
||||
ssd1306_intf.spi = 0;
|
||||
ssd1306_intf.start = &platform_i2c_start;
|
||||
ssd1306_intf.stop = &platform_i2c_stop;
|
||||
ssd1306_intf.send = &platform_i2c_send;
|
||||
ssd1306_intf.close = &platform_i2c_close;
|
||||
ssd1306_intf.send_buffer = &platform_i2c_send_buffer;
|
||||
}
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// !!! PLATFORM SPI IMPLEMENTATION OPTIONAL !!!
|
||||
#if defined(CONFIG_PLATFORM_SPI_AVAILABLE) && defined(CONFIG_PLATFORM_SPI_ENABLE)
|
||||
|
||||
#include "intf/spi/ssd1306_spi.h"
|
||||
#include "lcd/lcd_common.h"
|
||||
#include <SPI.h>
|
||||
|
||||
static void platform_spi_start(void)
|
||||
{
|
||||
digitalWrite(s_ssd1306_cs, LOW);
|
||||
}
|
||||
|
||||
static void platform_spi_stop(void)
|
||||
{
|
||||
if (ssd1306_lcd.type == LCD_TYPE_PCD8544)
|
||||
{
|
||||
digitalWrite(s_ssd1306_dc, LOW);
|
||||
SPI.transfer(0x00); // Send NOP command to allow last data byte to pass (bug in PCD8544?)
|
||||
// ssd1306 E3h is NOP command
|
||||
}
|
||||
if (s_ssd1306_cs >= 0)
|
||||
{
|
||||
digitalWrite(s_ssd1306_cs, HIGH);
|
||||
}
|
||||
}
|
||||
|
||||
static void platform_spi_send(uint8_t data)
|
||||
{
|
||||
SPI.transfer(data);
|
||||
}
|
||||
|
||||
static void platform_spi_close(void)
|
||||
{
|
||||
// ... free all spi resources here
|
||||
}
|
||||
|
||||
static void platform_spi_send_buffer(const uint8_t *data, uint16_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
SPI.transfer(*data);
|
||||
data++;
|
||||
};
|
||||
}
|
||||
|
||||
void ssd1306_platform_spiInit(int8_t busId,
|
||||
int8_t cesPin,
|
||||
int8_t dcPin)
|
||||
{
|
||||
if (cesPin >=0) pinMode(cesPin, OUTPUT);
|
||||
if (dcPin >= 0) pinMode(dcPin, OUTPUT);
|
||||
if (cesPin>=0) s_ssd1306_cs = cesPin;
|
||||
if (dcPin>=0) s_ssd1306_dc = dcPin;
|
||||
SPI.begin();
|
||||
ssd1306_intf.spi = 1;
|
||||
ssd1306_intf.start = &platform_spi_start;
|
||||
ssd1306_intf.stop = &platform_spi_stop;
|
||||
ssd1306_intf.send = &platform_spi_send;
|
||||
ssd1306_intf.close = &platform_spi_close;
|
||||
ssd1306_intf.send_buffer = &platform_spi_send_buffer;
|
||||
// init your interface here
|
||||
//...
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // SSD1306_ENERGIA_PLATFORM
|
||||
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018, Alexey Dynda
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file ssd1306_hal/esp/io.h This is stm32 platform file
|
||||
*/
|
||||
|
||||
#ifndef _SSD1306_ESP_IO_H_
|
||||
#define _SSD1306_ESP_IO_H_
|
||||
|
||||
// TODO: To complete support. Any help is welcome
|
||||
|
||||
#define SSD1306_ESP_PLATFORM
|
||||
//========================== I. Include libraries =========================
|
||||
/* 1. Include all required headers, specific for your platform here */
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define LOW 0
|
||||
#define HIGH 1
|
||||
#define INPUT 0
|
||||
#define OUTPUT 1
|
||||
/* Progmem attribute for data, located in Flash */
|
||||
#define PROGMEM
|
||||
|
||||
//========================== II. Define options ===========================
|
||||
/* 2. Uncomment all options, you have support for on your platform *
|
||||
* Remember that you will need to implement low level intf/i2c or *
|
||||
* intf/spi layers for your platform */
|
||||
|
||||
/** The macro is defined when STM32 i2c implementation is available */
|
||||
#define CONFIG_PLATFORM_I2C_AVAILABLE
|
||||
#define CONFIG_PLATFORM_SPI_AVAILABLE
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//========================== III. Implement functions =====================
|
||||
/* Implement functions below the way you like. You can make them non-static */
|
||||
// !!! MANDATORY !!!
|
||||
int digitalRead(int pin);
|
||||
|
||||
void digitalWrite(int pin, int level);
|
||||
|
||||
void pinMode(int pin, int mode);
|
||||
|
||||
static inline int analogRead(int pin) // analogRead()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t millis(void);
|
||||
|
||||
static inline uint32_t micros(void) // micros()
|
||||
{
|
||||
return 0;
|
||||
};
|
||||
|
||||
void delay(uint32_t ms);
|
||||
|
||||
static inline void delayMicroseconds(uint32_t us) // delayMicroseconds()
|
||||
{
|
||||
}
|
||||
|
||||
// !!! OPTIONAL !!!
|
||||
static inline void randomSeed(int seed) // randomSeed() - can be skipped
|
||||
{
|
||||
}
|
||||
|
||||
static inline void attachInterrupt(int pin, void (*interrupt)(), int level) // attachInterrupt() - can be skipped
|
||||
{
|
||||
}
|
||||
|
||||
static inline uint8_t pgm_read_byte(const void *ptr) // pgm_read_byte() - can be skipped
|
||||
{
|
||||
return *((const uint8_t *)ptr);
|
||||
}
|
||||
|
||||
static inline uint16_t eeprom_read_word(const void *ptr) // eeprom_read_word() - can be skipped
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void eeprom_write_word(const void *ptr, uint16_t val) // eeprom_write_word() - can be skipped
|
||||
{
|
||||
}
|
||||
|
||||
// utoa is already defined in stdlib c
|
||||
//static inline char *utoa(unsigned int num, char *str, int radix) // util utoa() - can be skipped
|
||||
//{
|
||||
// *str = '\0';
|
||||
// return str;
|
||||
//}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
static inline int random(int max) // random(n) - can be skipped if you don't use it
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int random(int min, int max) // random(a,b) - can be skipped if you don't use it
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,292 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018-2019, Alexey Dynda
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "ssd1306_hal/io.h"
|
||||
|
||||
#if defined(SSD1306_ESP_PLATFORM)
|
||||
|
||||
#include "intf/ssd1306_interface.h"
|
||||
#include "intf/spi/ssd1306_spi.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "driver/gpio.h"
|
||||
|
||||
#if 1
|
||||
|
||||
#if defined(CONFIG_PLATFORM_SPI_AVAILABLE) && defined(CONFIG_PLATFORM_SPI_ENABLE)
|
||||
static void platform_spi_send_cache();
|
||||
#endif
|
||||
|
||||
// TODO: To complete support. Any help is welcome
|
||||
int digitalRead(int pin) // digitalRead()
|
||||
{
|
||||
return gpio_get_level(pin);
|
||||
}
|
||||
|
||||
void digitalWrite(int pin, int level) // digitalWrite()
|
||||
{
|
||||
#if defined(CONFIG_PLATFORM_SPI_AVAILABLE) && defined(CONFIG_PLATFORM_SPI_ENABLE)
|
||||
if (s_ssd1306_dc == pin)
|
||||
{
|
||||
platform_spi_send_cache();
|
||||
}
|
||||
#endif
|
||||
gpio_set_level(pin, level);
|
||||
}
|
||||
|
||||
void pinMode(int pin, int mode)
|
||||
{
|
||||
if (mode == INPUT)
|
||||
gpio_set_direction(pin, GPIO_MODE_INPUT);
|
||||
else if (mode == OUTPUT)
|
||||
gpio_set_direction(pin, GPIO_MODE_OUTPUT);
|
||||
}
|
||||
|
||||
uint32_t millis(void)
|
||||
{
|
||||
return xTaskGetTickCount() * portTICK_PERIOD_MS;
|
||||
}
|
||||
|
||||
void delay(uint32_t ms) // delay()
|
||||
{
|
||||
vTaskDelay(ms / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// !!! PLATFORM I2C IMPLEMENTATION OPTIONAL !!!
|
||||
#if defined(CONFIG_PLATFORM_I2C_AVAILABLE) && defined(CONFIG_PLATFORM_I2C_ENABLE)
|
||||
|
||||
#include <stdio.h>
|
||||
#include "driver/i2c.h"
|
||||
|
||||
static uint8_t s_i2c_addr = 0x3C;
|
||||
static int8_t s_bus_id;
|
||||
|
||||
static i2c_cmd_handle_t s_cmd_handle = NULL;
|
||||
|
||||
static void platform_i2c_start(void)
|
||||
{
|
||||
// ... Open i2c channel for your device with specific s_i2c_addr
|
||||
if (s_cmd_handle == NULL)
|
||||
s_cmd_handle = i2c_cmd_link_create();
|
||||
i2c_master_start(s_cmd_handle);
|
||||
i2c_master_write_byte(s_cmd_handle, ( s_i2c_addr << 1 ) | I2C_MASTER_WRITE, 0x1);
|
||||
}
|
||||
|
||||
static void platform_i2c_stop(void)
|
||||
{
|
||||
// ... Complete i2c communication
|
||||
i2c_master_stop(s_cmd_handle);
|
||||
/*esp_err_t ret =*/ i2c_master_cmd_begin(s_bus_id, s_cmd_handle, 1000 / portTICK_RATE_MS);
|
||||
i2c_cmd_link_delete(s_cmd_handle);
|
||||
s_cmd_handle = NULL;
|
||||
}
|
||||
|
||||
static void platform_i2c_send(uint8_t data)
|
||||
{
|
||||
// ... Send byte to i2c communication channel
|
||||
i2c_master_write_byte(s_cmd_handle, data, 0x1);
|
||||
}
|
||||
|
||||
static void platform_i2c_close(void)
|
||||
{
|
||||
// ... free all i2c resources here
|
||||
i2c_driver_delete(s_bus_id);
|
||||
}
|
||||
|
||||
static void platform_i2c_send_buffer(const uint8_t *data, uint16_t len)
|
||||
{
|
||||
// ... Send len bytes to i2c communication channel here
|
||||
while (len--)
|
||||
{
|
||||
platform_i2c_send(*data);
|
||||
data++;
|
||||
}
|
||||
// i2c_master_write(cmd, data_wr, size, ACK_CHECK_EN);
|
||||
}
|
||||
|
||||
void ssd1306_platform_i2cInit(int8_t busId, uint8_t addr, ssd1306_platform_i2cConfig_t * cfg)
|
||||
{
|
||||
if (addr) s_i2c_addr = addr;
|
||||
ssd1306_intf.spi = 0;
|
||||
ssd1306_intf.start = &platform_i2c_start;
|
||||
ssd1306_intf.stop = &platform_i2c_stop;
|
||||
ssd1306_intf.send = &platform_i2c_send;
|
||||
ssd1306_intf.close = &platform_i2c_close;
|
||||
ssd1306_intf.send_buffer = &platform_i2c_send_buffer;
|
||||
// init your interface here
|
||||
if ( busId < 0) busId = I2C_NUM_1;
|
||||
s_bus_id = busId;
|
||||
i2c_config_t conf = { 0 };
|
||||
conf.mode = I2C_MODE_MASTER;
|
||||
conf.sda_io_num = cfg->sda >= 0 ? cfg->sda : 21;
|
||||
conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
|
||||
conf.scl_io_num = cfg->scl >= 0 ? cfg->scl : 22;
|
||||
conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
|
||||
conf.master.clk_speed = 400000; //I2C_EXAMPLE_MASTER_FREQ_HZ;
|
||||
i2c_param_config(s_bus_id, &conf);
|
||||
i2c_driver_install(s_bus_id, conf.mode, 0, 0, 0);
|
||||
// I2C_EXAMPLE_MASTER_RX_BUF_DISABLE,
|
||||
// I2C_EXAMPLE_MASTER_TX_BUF_DISABLE, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// !!! PLATFORM SPI IMPLEMENTATION OPTIONAL !!!
|
||||
#if defined(CONFIG_PLATFORM_SPI_AVAILABLE) && defined(CONFIG_PLATFORM_SPI_ENABLE)
|
||||
|
||||
#include "intf/spi/ssd1306_spi.h"
|
||||
#include "driver/spi_master.h"
|
||||
|
||||
// Store spi handle globally for all spi callbacks
|
||||
static spi_device_handle_t s_spi;
|
||||
static int8_t s_spi_bus_id;
|
||||
// s_first_spi_session is used for delayed spi initialization.
|
||||
// Some oled displays have slow max SPI speed, so display init function can change
|
||||
// spi frequency s_ssd1306_spi_clock. Register device, only when frequency is known.
|
||||
static uint8_t s_first_spi_session = 0;
|
||||
static uint8_t s_spi_cache[1024];
|
||||
static int s_spi_cached_count = 0;
|
||||
|
||||
static void platform_spi_send_cache()
|
||||
{
|
||||
/* TODO: Yeah, sending single bytes is too slow, but *
|
||||
* need to figure out how to detect data/command bytes *
|
||||
* to send bytes as one block */
|
||||
uint8_t *data = s_spi_cache;
|
||||
while (s_spi_cached_count)
|
||||
{
|
||||
size_t sz = s_spi_cached_count > 32 ? 32: s_spi_cached_count;
|
||||
spi_transaction_t t;
|
||||
memset(&t, 0, sizeof(t));
|
||||
t.length=8*sz; // 8 bits
|
||||
t.tx_buffer=data;
|
||||
// ... Send byte to spi communication channel
|
||||
// We do not care here about DC line state, because
|
||||
// ssd1306 library already set DC pin via ssd1306_spiDataMode() before call to send().
|
||||
spi_device_transmit(s_spi, &t);
|
||||
data+=sz;
|
||||
s_spi_cached_count-=sz;
|
||||
}
|
||||
s_spi_cached_count = 0;
|
||||
}
|
||||
|
||||
static void platform_spi_start(void)
|
||||
{
|
||||
// ... Open spi channel for your device with specific s_ssd1306_cs, s_ssd1306_dc
|
||||
if (s_first_spi_session)
|
||||
{
|
||||
spi_device_interface_config_t devcfg=
|
||||
{
|
||||
.clock_speed_hz = s_ssd1306_spi_clock,
|
||||
.mode=0,
|
||||
.spics_io_num=s_ssd1306_cs,
|
||||
.queue_size=7, // max 7 transactions at a time
|
||||
};
|
||||
spi_bus_add_device(s_spi_bus_id ? VSPI_HOST : HSPI_HOST, &devcfg, &s_spi);
|
||||
s_first_spi_session = 0;
|
||||
}
|
||||
s_spi_cached_count = 0;
|
||||
}
|
||||
|
||||
static void platform_spi_stop(void)
|
||||
{
|
||||
// ... Complete spi communication
|
||||
// no complete actions required for this implementation
|
||||
platform_spi_send_cache();
|
||||
}
|
||||
|
||||
static void platform_spi_send(uint8_t data)
|
||||
{
|
||||
s_spi_cache[s_spi_cached_count] = data;
|
||||
s_spi_cached_count++;
|
||||
if ( s_spi_cached_count >= sizeof( s_spi_cache ) )
|
||||
{
|
||||
platform_spi_send_cache();
|
||||
}
|
||||
}
|
||||
|
||||
static void platform_spi_close(void)
|
||||
{
|
||||
// ... free all spi resources here
|
||||
if (!s_first_spi_session)
|
||||
{
|
||||
spi_bus_remove_device( s_spi );
|
||||
}
|
||||
spi_bus_free( s_spi_bus_id ? VSPI_HOST : HSPI_HOST );
|
||||
}
|
||||
|
||||
static void platform_spi_send_buffer(const uint8_t *data, uint16_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
platform_spi_send(*data);
|
||||
data++;
|
||||
}
|
||||
}
|
||||
|
||||
void ssd1306_platform_spiInit(int8_t busId,
|
||||
int8_t cesPin,
|
||||
int8_t dcPin)
|
||||
{
|
||||
// Use VSPI by default
|
||||
if (busId < 0) busId = 1;
|
||||
s_spi_bus_id = busId;
|
||||
|
||||
// If cesPin is not provided, select by default
|
||||
if (cesPin < 0)
|
||||
{
|
||||
cesPin = s_spi_bus_id ? 5 : 15;
|
||||
}
|
||||
s_ssd1306_cs = cesPin;
|
||||
if (dcPin>=0) s_ssd1306_dc = dcPin;
|
||||
|
||||
if (cesPin >=0) pinMode(cesPin, OUTPUT);
|
||||
if (dcPin >= 0) pinMode(dcPin, OUTPUT);
|
||||
|
||||
ssd1306_intf.spi = 1;
|
||||
ssd1306_intf.start = &platform_spi_start;
|
||||
ssd1306_intf.stop = &platform_spi_stop;
|
||||
ssd1306_intf.send = &platform_spi_send;
|
||||
ssd1306_intf.close = &platform_spi_close;
|
||||
ssd1306_intf.send_buffer = &platform_spi_send_buffer;
|
||||
|
||||
// init your interface here
|
||||
spi_bus_config_t buscfg=
|
||||
{
|
||||
.miso_io_num= s_spi_bus_id ? 19 : 12,
|
||||
.mosi_io_num= s_spi_bus_id ? 23 : 13,
|
||||
.sclk_io_num= s_spi_bus_id ? 18 : 14,
|
||||
.quadwp_io_num=-1,
|
||||
.quadhd_io_num=-1,
|
||||
.max_transfer_sz=32
|
||||
};
|
||||
spi_bus_initialize(s_spi_bus_id ? VSPI_HOST : HSPI_HOST, &buscfg, 0); // 0 -no dma
|
||||
s_first_spi_session = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // SSD1306_ESP_PLATFORM
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018, Alexey Dynda
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file ssd1306_hal/io.h SSD1306 HAL IO communication functions
|
||||
*/
|
||||
|
||||
#ifndef _SSD1306_HAL_IO_H_
|
||||
#define _SSD1306_HAL_IO_H_
|
||||
|
||||
/**
|
||||
* @defgroup SSD1306_HAL_API HAL: ssd1306 library hardware abstraction layer
|
||||
* @{
|
||||
*
|
||||
* @brief i2c/spi ssd1306 library hardware abstraction layer
|
||||
*
|
||||
* @details ssd1306 library hardware abstraction layer
|
||||
*/
|
||||
|
||||
#include "UserSettings.h"
|
||||
#if defined(ARDUINO) && !defined(ENERGIA)
|
||||
#include "arduino/io.h"
|
||||
#elif defined(__AVR__) && !defined(ARDUINO)
|
||||
#include "avr/io.h"
|
||||
#elif defined(__XTENSA__) && !defined(ARDUINO)
|
||||
#include "esp/io.h"
|
||||
#elif defined(STM32F1) || defined(STM32F2) || defined(STM32F4)
|
||||
#include "stm32/io.h"
|
||||
#elif defined(__linux__)
|
||||
#include "linux/io.h"
|
||||
#elif defined(__MINGW32__)
|
||||
#include "mingw/io.h"
|
||||
#elif defined(ENERGIA)
|
||||
#include "energia/io.h"
|
||||
#else
|
||||
#warning "Platform is not supported. Use template to add support"
|
||||
#include "template/io.h"
|
||||
#endif
|
||||
|
||||
#ifndef LCDINT_TYPES_DEFINED
|
||||
/** Macro informs if lcdint_t type is defined */
|
||||
#define LCDINT_TYPES_DEFINED
|
||||
/** internal int type, used by ssd1306 library. Important for uC with low SRAM */
|
||||
typedef int lcdint_t;
|
||||
/** internal int type, used by ssd1306 library. Important for uC with low SRAM */
|
||||
typedef unsigned int lcduint_t;
|
||||
#endif
|
||||
|
||||
/** swaps content of a and b variables of type type */
|
||||
#define ssd1306_swap_data(a, b, type) { type t = a; a = b; b = t; }
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// !!! PLATFORM I2C IMPLEMENTATION OPTIONAL !!!
|
||||
#if defined(CONFIG_PLATFORM_I2C_AVAILABLE) && defined(CONFIG_PLATFORM_I2C_ENABLE)
|
||||
/**
|
||||
* Structure describes i2c pins used by platform
|
||||
*/
|
||||
typedef struct {
|
||||
int8_t sda; ///< data pin number
|
||||
int8_t scl; ///< clock pin number
|
||||
} ssd1306_platform_i2cConfig_t;
|
||||
|
||||
/**
|
||||
* @brief Initializes i2c interface for platform being used.
|
||||
*
|
||||
* Initializes i2c interface for platform being used. i2c implementation
|
||||
* depends on platform.
|
||||
*
|
||||
* @param busId i2c bus number. Some platforms have several i2c buses. so, this
|
||||
* argument identifies bus to use. For several platforms busId is not used.
|
||||
* If you want to use default i2c bus for specific platform, please pass -1.
|
||||
* @param addr i2c address of oled driver, connected to i2c bus. If you want to use default
|
||||
* i2c display address, please, pass 0.
|
||||
* @param cfg Specify scl and sda for the platform. If you want to use default pin numbers,
|
||||
* please pass -1 for both members.
|
||||
*/
|
||||
void ssd1306_platform_i2cInit(int8_t busId, uint8_t addr, ssd1306_platform_i2cConfig_t * cfg);
|
||||
#endif
|
||||
|
||||
|
||||
// !!! PLATFORM SPI IMPLEMENTATION OPTIONAL !!!
|
||||
#if defined(CONFIG_PLATFORM_SPI_AVAILABLE) && defined(CONFIG_PLATFORM_SPI_ENABLE)
|
||||
/**
|
||||
* @brief Initializes spi interface for platform being used.
|
||||
*
|
||||
* Initializes spi interface for platform being used. spi implementation
|
||||
* depends on platform.
|
||||
*
|
||||
* @param busId spi bus number if device has several spi buses. For most AVR platforms
|
||||
* busId is not used. If you want to use default spi bus for specific platform, please
|
||||
* pass -1.
|
||||
* @param cesPin chip select (chip enable) pin number. If you want to use default pin,
|
||||
* hard coded by ssd1306 library, please, pass -1. For Linux platform cesPin means
|
||||
* second number in spidev device.
|
||||
* @param dcPin data/command pin number. For most oled displays this pin number is used to
|
||||
* select data or command mode for the bus. If you want to use default pin number, please
|
||||
* pass -1.
|
||||
*/
|
||||
void ssd1306_platform_spiInit(int8_t busId, int8_t cesPin, int8_t dcPin);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
#ifndef _ARDUINO_H_
|
||||
#define _ARDUINO_H_
|
||||
|
||||
#define ARDUINO_FAKE
|
||||
#if defined(__MINGW32__)
|
||||
#include "ssd1306_hal/mingw/io.h"
|
||||
#include "ssd1306_hal/Print_internal.h"
|
||||
#else
|
||||
#include "ssd1306_hal/linux/io.h"
|
||||
#include "ssd1306_hal/Print_internal.h"
|
||||
#endif
|
||||
|
||||
#ifndef boolean
|
||||
typedef uint8_t boolean;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
#ifndef _PRINT_H_
|
||||
#define _PRINT_H_
|
||||
|
||||
#include "ssd1306_hal/io.h"
|
||||
#include "ssd1306_hal/Print_internal.h"
|
||||
|
||||
#define __FlashStringHelper char
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018, Alexey Dynda
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file ssd1306_hal/linux/io.h SSD1306 LINUX IO communication functions
|
||||
*/
|
||||
|
||||
#ifndef _SSD1306_LINUX_IO_H_
|
||||
#define _SSD1306_LINUX_IO_H_
|
||||
|
||||
#define CONFIG_PLATFORM_I2C_AVAILABLE
|
||||
#define CONFIG_PLATFORM_SPI_AVAILABLE
|
||||
|
||||
|
||||
#if defined(SDL_EMULATION) // SDL Emulation mode includes
|
||||
#include "sdl_core.h"
|
||||
#endif
|
||||
|
||||
#if defined(__KERNEL__) // KERNEL includes
|
||||
#include <linux/types.h>
|
||||
|
||||
#else // LINUX includes
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
/** Standard defines */
|
||||
#define LOW 0
|
||||
#define HIGH 1
|
||||
#define INPUT 1
|
||||
#define OUTPUT 0
|
||||
/** Pure linux implementation of the library doesn't support data, located in code area */
|
||||
#define PROGMEM
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(__KERNEL__) // ============== KERNEL
|
||||
static inline int digitalRead(int pin) { return LOW; };
|
||||
static inline void delay(unsigned long ms) { };
|
||||
static inline void delayMicroseconds(unsigned long us) { };
|
||||
static inline int analogRead(int pin) { return 0; };
|
||||
static inline void digitalWrite(int pin, int level) { };
|
||||
static inline uint32_t millis(void) { return 0; };
|
||||
static inline uint32_t micros(void) { return 0; };
|
||||
static inline void pinMode(int pin, int mode) {};
|
||||
|
||||
#else // ============== LINUX
|
||||
static inline void delay(unsigned long ms) { usleep(ms*1000); };
|
||||
static inline void delayMicroseconds(unsigned long us) { usleep(us); };
|
||||
static inline uint32_t millis(void)
|
||||
{
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
return ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
|
||||
};
|
||||
|
||||
static inline uint32_t micros(void)
|
||||
{
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
return ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
|
||||
};
|
||||
|
||||
/* For some reason defines do not work accross the libraries *
|
||||
* Didn't yet figure out, what is the reason fo this issue */
|
||||
//define min(a,b) (((a)<(b))?(a):(b))
|
||||
//define max(a,b) (((a)>(b))?(a):(b))
|
||||
static inline int min(int a, int b) { return a<b?a:b; };
|
||||
static inline int max(int a, int b) { return a>b?a:b; };
|
||||
#if !defined(SDL_EMULATION)
|
||||
void pinMode(int pin, int mode);
|
||||
static inline int digitalRead(int pin) { return LOW; };
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(SDL_EMULATION)
|
||||
static inline int digitalRead(int pin) { return sdl_read_digital(pin); };
|
||||
static inline int analogRead(int pin) { return sdl_read_analog(pin); };
|
||||
static inline void digitalWrite(int pin, int level) { sdl_write_digital(pin, level); };
|
||||
static inline void pinMode(int pin, int mode) { };
|
||||
#elif !defined(__KERNEL__)
|
||||
static inline int analogRead(int pin) { return 0; };
|
||||
void digitalWrite(int pin, int level);
|
||||
#endif
|
||||
|
||||
static inline void randomSeed(int seed) { };
|
||||
static inline void attachInterrupt(int pin, void (*interrupt)(void), int level) { };
|
||||
static inline uint8_t pgm_read_byte(const void *ptr) { return *((const uint8_t *)ptr); };
|
||||
static inline uint16_t eeprom_read_word(const void *ptr) { return 0; };
|
||||
static inline void eeprom_write_word(const void *ptr, uint16_t val) { };
|
||||
|
||||
static inline char *utoa(unsigned int num, char *str, int radix)
|
||||
{
|
||||
char temp[17]; //an int can only be 16 bits long
|
||||
//at radix 2 (binary) the string
|
||||
//is at most 16 + 1 null long.
|
||||
int temp_loc = 0;
|
||||
int str_loc = 0;
|
||||
|
||||
//construct a backward string of the number.
|
||||
do {
|
||||
int digit = (unsigned int)num % radix;
|
||||
if (digit < 10)
|
||||
temp[temp_loc++] = digit + '0';
|
||||
else
|
||||
temp[temp_loc++] = digit - 10 + 'A';
|
||||
num = ((unsigned int)num) / radix;
|
||||
} while ((unsigned int)num > 0);
|
||||
|
||||
temp_loc--;
|
||||
|
||||
|
||||
//now reverse the string.
|
||||
while ( temp_loc >=0 ) {// while there are still chars
|
||||
str[str_loc++] = temp[temp_loc--];
|
||||
}
|
||||
str[str_loc] = 0; // add null termination.
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <cstdlib>
|
||||
static inline long random(long v)
|
||||
{
|
||||
return rand() % v;
|
||||
}
|
||||
|
||||
static inline long random(long min, long max)
|
||||
{
|
||||
return rand() % (max - min + 1) + min;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,583 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018-2019, Alexey Dynda
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#if defined(__linux__) && !defined(ARDUINO)
|
||||
|
||||
#include "ssd1306_hal/io.h"
|
||||
#include "intf/ssd1306_interface.h"
|
||||
#include "intf/i2c/ssd1306_i2c.h"
|
||||
#include "intf/spi/ssd1306_spi_conf.h"
|
||||
#include "intf/spi/ssd1306_spi.h"
|
||||
|
||||
#ifndef __KERNEL__
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/i2c-dev.h>
|
||||
#include <linux/spi/spidev.h>
|
||||
|
||||
#if defined(CONFIG_PLATFORM_SPI_AVAILABLE) && defined(CONFIG_PLATFORM_SPI_ENABLE) \
|
||||
&& !defined(SDL_EMULATION)
|
||||
#define LINUX_SPI_AVAILABLE
|
||||
#endif
|
||||
|
||||
#define MAX_GPIO_COUNT 256
|
||||
|
||||
#ifdef IN
|
||||
#undef IN
|
||||
#endif
|
||||
#define IN 0
|
||||
|
||||
#ifdef OUT
|
||||
#undef OUT
|
||||
#endif
|
||||
#define OUT 1
|
||||
|
||||
#ifdef LINUX_SPI_AVAILABLE
|
||||
static void platform_spi_send_cache();
|
||||
#endif
|
||||
|
||||
int gpio_export(int pin)
|
||||
{
|
||||
char buffer[4];
|
||||
ssize_t bytes_written;
|
||||
int fd;
|
||||
char path[64];
|
||||
|
||||
snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d", pin);
|
||||
|
||||
if (access(path, F_OK) == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
fd = open("/sys/class/gpio/export", O_WRONLY);
|
||||
if (-1 == fd)
|
||||
{
|
||||
fprintf(stderr, "Failed to allocate gpio pin[%d]: %s%s!\n",
|
||||
pin, strerror (errno), getuid() == 0 ? "" : ", need to be root");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
bytes_written = snprintf(buffer, sizeof(buffer), "%d", pin);
|
||||
if (write(fd, buffer, bytes_written) < 0)
|
||||
{
|
||||
fprintf(stderr, "Failed to allocate gpio pin[%d]: %s%s!\n",
|
||||
pin, strerror (errno), getuid() == 0 ? "" : ", need to be root");
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
close(fd);
|
||||
return(0);
|
||||
}
|
||||
|
||||
int gpio_unexport(int pin)
|
||||
{
|
||||
char buffer[4];
|
||||
ssize_t bytes_written;
|
||||
int fd;
|
||||
|
||||
fd = open("/sys/class/gpio/unexport", O_WRONLY);
|
||||
if (-1 == fd)
|
||||
{
|
||||
fprintf(stderr, "Failed to free gpio pin resources!\n");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
bytes_written = snprintf(buffer, sizeof(buffer), "%d", pin);
|
||||
if (write(fd, buffer, bytes_written) < 0)
|
||||
{
|
||||
fprintf(stderr, "Failed to free gpio pin resources!\n");
|
||||
}
|
||||
close(fd);
|
||||
return(0);
|
||||
}
|
||||
|
||||
int gpio_direction(int pin, int dir)
|
||||
{
|
||||
static const char s_directions_str[] = "in\0out";
|
||||
|
||||
char path[64];
|
||||
int fd;
|
||||
|
||||
snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/direction", pin);
|
||||
fd = open(path, O_WRONLY);
|
||||
if (-1 == fd)
|
||||
{
|
||||
fprintf(stderr, "Failed to set gpio pin direction1[%d]: %s!\n",
|
||||
pin, strerror(errno));
|
||||
return(-1);
|
||||
}
|
||||
|
||||
if (-1 == write(fd, &s_directions_str[IN == dir ? 0 : 3], IN == dir ? 2 : 3))
|
||||
{
|
||||
fprintf(stderr, "Failed to set gpio pin direction2[%d]: %s!\n",
|
||||
pin, strerror(errno));
|
||||
return(-1);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return(0);
|
||||
}
|
||||
|
||||
int gpio_read(int pin)
|
||||
{
|
||||
char path[32];
|
||||
char value_str[3];
|
||||
int fd;
|
||||
|
||||
snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/value", pin);
|
||||
fd = open(path, O_RDONLY);
|
||||
if (-1 == fd)
|
||||
{
|
||||
fprintf(stderr, "Failed to read gpio pin value!\n");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
if (-1 == read(fd, value_str, 3))
|
||||
{
|
||||
fprintf(stderr, "Failed to read gpio pin value!\n");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
return(atoi(value_str));
|
||||
}
|
||||
|
||||
int gpio_write(int pin, int value)
|
||||
{
|
||||
static const char s_values_str[] = "01";
|
||||
|
||||
char path[64];
|
||||
int fd;
|
||||
|
||||
snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/value", pin);
|
||||
fd = open(path, O_WRONLY);
|
||||
if (-1 == fd)
|
||||
{
|
||||
fprintf(stderr, "Failed to set gpio pin value[%d]: %s%s!\n",
|
||||
pin, strerror (errno), getuid() == 0 ? "" : ", need to be root");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
if (1 != write(fd, &s_values_str[LOW == value ? 0 : 1], 1))
|
||||
{
|
||||
fprintf(stderr, "Failed to set gpio pin value[%d]: %s%s!\n",
|
||||
pin, strerror (errno), getuid() == 0 ? "" : ", need to be root");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return(0);
|
||||
}
|
||||
|
||||
#if !defined(SDL_EMULATION)
|
||||
|
||||
static uint8_t s_exported_pin[MAX_GPIO_COUNT] = {0};
|
||||
static uint8_t s_pin_mode[MAX_GPIO_COUNT] = {0};
|
||||
|
||||
void pinMode(int pin, int mode)
|
||||
{
|
||||
if (!s_exported_pin[pin])
|
||||
{
|
||||
if ( gpio_export(pin)<0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
s_exported_pin[pin] = 1;
|
||||
}
|
||||
if (mode == OUTPUT)
|
||||
{
|
||||
gpio_direction(pin, OUT);
|
||||
s_pin_mode[pin] = 1;
|
||||
}
|
||||
if (mode == INPUT)
|
||||
{
|
||||
gpio_direction(pin, IN);
|
||||
s_pin_mode[pin] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void digitalWrite(int pin, int level)
|
||||
{
|
||||
#ifdef LINUX_SPI_AVAILABLE
|
||||
if (s_ssd1306_dc == pin)
|
||||
{
|
||||
platform_spi_send_cache();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!s_exported_pin[pin])
|
||||
{
|
||||
if ( gpio_export(pin)<0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
s_exported_pin[pin] = 1;
|
||||
}
|
||||
if (!s_pin_mode[pin])
|
||||
{
|
||||
pinMode(pin, OUTPUT);
|
||||
}
|
||||
gpio_write( pin, level );
|
||||
}
|
||||
|
||||
#endif // SDL_EMULATION
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// LINUX I2C IMPLEMENTATION
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
#if defined(CONFIG_PLATFORM_I2C_AVAILABLE) && defined(CONFIG_PLATFORM_I2C_ENABLE)
|
||||
|
||||
|
||||
|
||||
#if !defined(SDL_EMULATION)
|
||||
|
||||
|
||||
static uint8_t s_sa = SSD1306_SA;
|
||||
static int s_fd = -1;
|
||||
static uint8_t s_buffer[128];
|
||||
static uint8_t s_dataSize = 0;
|
||||
|
||||
static void platform_i2c_start(void)
|
||||
{
|
||||
s_dataSize = 0;
|
||||
}
|
||||
|
||||
static void platform_i2c_stop(void)
|
||||
{
|
||||
if (write(s_fd, s_buffer, s_dataSize) != s_dataSize)
|
||||
{
|
||||
fprintf(stderr, "Failed to write to the i2c bus: %s.\n", strerror(errno));
|
||||
}
|
||||
s_dataSize = 0;
|
||||
}
|
||||
|
||||
static void platform_i2c_send(uint8_t data)
|
||||
{
|
||||
s_buffer[s_dataSize] = data;
|
||||
s_dataSize++;
|
||||
if (s_dataSize == sizeof(s_buffer))
|
||||
{
|
||||
/* Send function puts all data to internal buffer. *
|
||||
* Restart transmission if internal buffer is full. */
|
||||
ssd1306_intf.stop();
|
||||
ssd1306_intf.start();
|
||||
ssd1306_intf.send(0x40);
|
||||
}
|
||||
}
|
||||
|
||||
static void platform_i2c_send_buffer(const uint8_t *buffer, uint16_t size)
|
||||
{
|
||||
while (size--)
|
||||
{
|
||||
platform_i2c_send(*buffer);
|
||||
buffer++;
|
||||
}
|
||||
}
|
||||
|
||||
static void platform_i2c_close()
|
||||
{
|
||||
if (s_fd >= 0)
|
||||
{
|
||||
close(s_fd);
|
||||
s_fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
static void empty_function()
|
||||
{
|
||||
}
|
||||
|
||||
static void empty_function_single_arg(uint8_t arg)
|
||||
{
|
||||
}
|
||||
|
||||
static void empty_function_two_args(const uint8_t *arg1, uint16_t arg2)
|
||||
{
|
||||
}
|
||||
|
||||
void ssd1306_platform_i2cInit(int8_t busId, uint8_t sa, ssd1306_platform_i2cConfig_t * cfg)
|
||||
{
|
||||
char filename[20];
|
||||
if (busId < 0)
|
||||
{
|
||||
busId = 1;
|
||||
}
|
||||
snprintf(filename, 19, "/dev/i2c-%d", busId);
|
||||
ssd1306_intf.start = empty_function;
|
||||
ssd1306_intf.stop = empty_function;
|
||||
ssd1306_intf.close = empty_function;
|
||||
ssd1306_intf.send = empty_function_single_arg;
|
||||
ssd1306_intf.send_buffer = empty_function_two_args;
|
||||
if ((s_fd = open(filename, O_RDWR)) < 0)
|
||||
{
|
||||
fprintf(stderr, "Failed to open the i2c bus %s\n",
|
||||
getuid() == 0 ? "": ": need to be root");
|
||||
return;
|
||||
}
|
||||
if (sa)
|
||||
{
|
||||
s_sa = sa;
|
||||
}
|
||||
if (ioctl(s_fd, I2C_SLAVE, s_sa) < 0)
|
||||
{
|
||||
fprintf(stderr, "Failed to acquire bus access and/or talk to slave.\n");
|
||||
return;
|
||||
}
|
||||
ssd1306_intf.start = platform_i2c_start;
|
||||
ssd1306_intf.stop = platform_i2c_stop;
|
||||
ssd1306_intf.send = platform_i2c_send;
|
||||
ssd1306_intf.send_buffer = platform_i2c_send_buffer;
|
||||
ssd1306_intf.close = platform_i2c_close;
|
||||
}
|
||||
|
||||
#else /* SDL_EMULATION */
|
||||
|
||||
#include "sdl_core.h"
|
||||
|
||||
static void platform_i2c_send_buffer(const uint8_t *buffer, uint16_t size)
|
||||
{
|
||||
while (size--)
|
||||
{
|
||||
sdl_send_byte(*buffer);
|
||||
buffer++;
|
||||
};
|
||||
}
|
||||
|
||||
void ssd1306_platform_i2cInit(int8_t busId, uint8_t sa, ssd1306_platform_i2cConfig_t * cfg)
|
||||
{
|
||||
sdl_core_init();
|
||||
ssd1306_intf.spi = 0;
|
||||
ssd1306_intf.start = sdl_send_init;
|
||||
ssd1306_intf.stop = sdl_send_stop;
|
||||
ssd1306_intf.send = sdl_send_byte;
|
||||
ssd1306_intf.send_buffer = platform_i2c_send_buffer;
|
||||
ssd1306_intf.close = sdl_core_close;
|
||||
}
|
||||
|
||||
#endif /* SDL_EMULATION */
|
||||
|
||||
#endif // CONFIG_PLATFORM_I2C_AVAILABLE
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// LINUX SPI IMPLEMENTATION
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
#if defined(CONFIG_PLATFORM_SPI_AVAILABLE) && defined(CONFIG_PLATFORM_SPI_ENABLE)
|
||||
|
||||
#if !defined(SDL_EMULATION)
|
||||
|
||||
static int s_spi_fd = -1;
|
||||
extern uint32_t s_ssd1306_spi_clock;
|
||||
static uint8_t s_spi_cache[1024];
|
||||
static int s_spi_cached_count = 0;
|
||||
|
||||
static void platform_spi_start(void)
|
||||
{
|
||||
s_spi_cached_count = 0;
|
||||
}
|
||||
|
||||
static void platform_spi_stop(void)
|
||||
{
|
||||
platform_spi_send_cache();
|
||||
}
|
||||
|
||||
static void platform_spi_send_cache()
|
||||
{
|
||||
/* TODO: Yeah, sending single bytes is too slow, but *
|
||||
* need to figure out how to detect data/command bytes *
|
||||
* to send bytes as one block */
|
||||
if ( s_spi_cached_count == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
struct spi_ioc_transfer mesg;
|
||||
memset(&mesg, 0, sizeof mesg);
|
||||
mesg.tx_buf = (unsigned long)&s_spi_cache[0];
|
||||
mesg.rx_buf = 0;
|
||||
mesg.len = s_spi_cached_count;
|
||||
mesg.delay_usecs = 0;
|
||||
mesg.speed_hz = 0;
|
||||
mesg.bits_per_word = 8;
|
||||
mesg.cs_change = 0;
|
||||
if (ioctl(s_spi_fd, SPI_IOC_MESSAGE(1), &mesg) < 1)
|
||||
{
|
||||
fprintf(stderr, "SPI failed to send SPI message: %s\n", strerror (errno)) ;
|
||||
}
|
||||
s_spi_cached_count = 0;
|
||||
}
|
||||
|
||||
static void platform_spi_send(uint8_t data)
|
||||
{
|
||||
s_spi_cache[s_spi_cached_count] = data;
|
||||
s_spi_cached_count++;
|
||||
if ( s_spi_cached_count >= sizeof( s_spi_cache ) )
|
||||
{
|
||||
platform_spi_send_cache();
|
||||
}
|
||||
}
|
||||
|
||||
static void platform_spi_close(void)
|
||||
{
|
||||
if (s_spi_fd >= 0)
|
||||
{
|
||||
close(s_spi_fd);
|
||||
s_spi_fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
static void platform_spi_send_buffer(const uint8_t *data, uint16_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
platform_spi_send(*data);
|
||||
data++;
|
||||
}
|
||||
}
|
||||
|
||||
static void empty_function_spi(void)
|
||||
{
|
||||
}
|
||||
|
||||
static void empty_function_arg_spi(uint8_t byte)
|
||||
{
|
||||
}
|
||||
|
||||
static void empty_function_args_spi(const uint8_t *buffer, uint16_t bytes)
|
||||
{
|
||||
}
|
||||
|
||||
void ssd1306_platform_spiInit(int8_t busId,
|
||||
int8_t ces,
|
||||
int8_t dcPin)
|
||||
{
|
||||
char filename[20];
|
||||
if (busId < 0)
|
||||
{
|
||||
busId = 0;
|
||||
}
|
||||
if (ces < 0)
|
||||
{
|
||||
ces = 0;
|
||||
}
|
||||
s_ssd1306_cs = -1; // SPI interface does't need separate ces pin
|
||||
s_ssd1306_dc = dcPin;
|
||||
ssd1306_intf.spi = 1;
|
||||
ssd1306_intf.start = empty_function_spi;
|
||||
ssd1306_intf.stop = empty_function_spi;
|
||||
ssd1306_intf.send = empty_function_arg_spi;
|
||||
ssd1306_intf.send_buffer = empty_function_args_spi;
|
||||
ssd1306_intf.close = empty_function;
|
||||
|
||||
snprintf(filename, 19, "/dev/spidev%d.%d", busId, ces);
|
||||
if ((s_spi_fd = open(filename, O_RDWR)) < 0)
|
||||
{
|
||||
printf("Failed to initialize SPI: %s%s!\n",
|
||||
strerror(errno), getuid() == 0 ? "": ", need to be root");
|
||||
return;
|
||||
}
|
||||
unsigned int speed = s_ssd1306_spi_clock;
|
||||
if (ioctl(s_spi_fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed) < 0)
|
||||
{
|
||||
printf("Failed to set speed on SPI line: %s!\n", strerror(errno));
|
||||
}
|
||||
uint8_t mode = SPI_MODE_0;
|
||||
if (ioctl (s_spi_fd, SPI_IOC_WR_MODE, &mode) < 0)
|
||||
{
|
||||
printf("Failed to set SPI mode: %s!\n", strerror(errno));
|
||||
}
|
||||
uint8_t spi_bpw = 8;
|
||||
if (ioctl (s_spi_fd, SPI_IOC_WR_BITS_PER_WORD, &spi_bpw) < 0)
|
||||
{
|
||||
printf("Failed to set SPI BPW: %s!\n", strerror(errno));
|
||||
}
|
||||
|
||||
ssd1306_intf.spi = 1;
|
||||
ssd1306_intf.start = platform_spi_start;
|
||||
ssd1306_intf.stop = platform_spi_stop;
|
||||
ssd1306_intf.send = platform_spi_send;
|
||||
ssd1306_intf.send_buffer = platform_spi_send_buffer;
|
||||
ssd1306_intf.close = platform_spi_close;
|
||||
}
|
||||
|
||||
#else /* SDL_EMULATION */
|
||||
|
||||
#include "sdl_core.h"
|
||||
|
||||
static void sdl_send_bytes(const uint8_t *buffer, uint16_t size)
|
||||
{
|
||||
while (size--)
|
||||
{
|
||||
sdl_send_byte(*buffer);
|
||||
buffer++;
|
||||
};
|
||||
}
|
||||
|
||||
void ssd1306_platform_spiInit(int8_t busId, int8_t ces, int8_t dcPin)
|
||||
{
|
||||
sdl_core_init();
|
||||
if (ces >= 0)
|
||||
{
|
||||
s_ssd1306_cs = ces;
|
||||
}
|
||||
if (dcPin >= 0)
|
||||
{
|
||||
s_ssd1306_dc = dcPin;
|
||||
}
|
||||
sdl_set_dc_pin(dcPin);
|
||||
ssd1306_intf.spi = 1;
|
||||
ssd1306_intf.start = sdl_send_init;
|
||||
ssd1306_intf.stop = sdl_send_stop;
|
||||
ssd1306_intf.send = sdl_send_byte;
|
||||
ssd1306_intf.send_buffer = sdl_send_bytes;
|
||||
ssd1306_intf.close = sdl_core_close;
|
||||
}
|
||||
|
||||
#endif /* SDL_EMULATION */
|
||||
|
||||
#endif // CONFIG_PLATFORM_SPI_AVAILABLE
|
||||
|
||||
#else // end of !KERNEL, KERNEL is below
|
||||
|
||||
void ssd1306_platform_i2cInit(int8_t busId, uint8_t sa, ssd1306_platform_i2cConfig_t * cfg)
|
||||
{
|
||||
}
|
||||
|
||||
void ssd1306_platform_spiInit(int8_t busId,
|
||||
int8_t ces,
|
||||
int8_t dcPin)
|
||||
{
|
||||
}
|
||||
|
||||
#endif // KERNEL
|
||||
|
||||
#endif // __linux__
|
||||
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018, Alexey Dynda
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file ssd1306_hal/mingw/io.h SSD1306 MINGW IO communication functions
|
||||
*/
|
||||
|
||||
#ifndef _SSD1306_MINGW_IO_H_
|
||||
#define _SSD1306_MINGW_IO_H_
|
||||
|
||||
// Use the same library interface as for Linux
|
||||
#define CONFIG_PLATFORM_I2C_AVAILABLE
|
||||
#define CONFIG_PLATFORM_SPI_AVAILABLE
|
||||
|
||||
#if defined(SDL_EMULATION) // SDL Emulation mode includes
|
||||
#include "sdl_core.h"
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include "sdl_core.h"
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
|
||||
/** Standard defines */
|
||||
#define LOW 0
|
||||
#define HIGH 1
|
||||
#define INPUT 1
|
||||
#define OUTPUT 0
|
||||
/** Pure linux implementation of the library doesn't support data, located in code area */
|
||||
#define PROGMEM
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static inline int digitalRead(int pin) { return sdl_read_digital(pin); };
|
||||
static inline void delay(unsigned long ms) { Sleep(ms); };
|
||||
static inline void delayMicroseconds(unsigned long us) { Sleep((us+500)/1000); };
|
||||
static inline uint32_t millis(void)
|
||||
{
|
||||
return GetTickCount();
|
||||
};
|
||||
|
||||
static inline uint32_t micros(void)
|
||||
{
|
||||
return GetTickCount()*1000;
|
||||
};
|
||||
|
||||
#if defined(SDL_EMULATION)
|
||||
static inline int analogRead(int pin) { return sdl_read_analog(pin); };
|
||||
static inline void digitalWrite(int pin, int level) { sdl_write_digital(pin, level); };
|
||||
static inline void pinMode(int pin, int mode) { };
|
||||
#endif
|
||||
|
||||
static inline void randomSeed(int seed) { };
|
||||
static inline void attachInterrupt(int pin, void (*interrupt)(void), int level) { };
|
||||
static inline uint8_t pgm_read_byte(const void *ptr) { return *((const uint8_t *)ptr); };
|
||||
static inline uint16_t eeprom_read_word(const void *ptr) { return 0; };
|
||||
static inline void eeprom_write_word(const void *ptr, uint16_t val) { };
|
||||
|
||||
static inline char *utoa(unsigned int num, char *str, int radix)
|
||||
{
|
||||
char temp[17]; //an int can only be 16 bits long
|
||||
//at radix 2 (binary) the string
|
||||
//is at most 16 + 1 null long.
|
||||
int temp_loc = 0;
|
||||
int str_loc = 0;
|
||||
|
||||
//construct a backward string of the number.
|
||||
do {
|
||||
int digit = (unsigned int)num % radix;
|
||||
if (digit < 10)
|
||||
temp[temp_loc++] = digit + '0';
|
||||
else
|
||||
temp[temp_loc++] = digit - 10 + 'A';
|
||||
num = ((unsigned int)num) / radix;
|
||||
} while ((unsigned int)num > 0);
|
||||
|
||||
temp_loc--;
|
||||
|
||||
|
||||
//now reverse the string.
|
||||
while ( temp_loc >=0 ) {// while there are still chars
|
||||
str[str_loc++] = temp[temp_loc--];
|
||||
}
|
||||
str[str_loc] = 0; // add null termination.
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <cstdlib>
|
||||
static inline long random(long v)
|
||||
{
|
||||
return rand() % v;
|
||||
}
|
||||
|
||||
static inline long random(long min, long max)
|
||||
{
|
||||
return rand() % (max - min + 1) + min;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,342 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018, Alexey Dynda
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#if defined(__MINGW32__)
|
||||
|
||||
#include "ssd1306_hal/io.h"
|
||||
|
||||
#include "intf/ssd1306_interface.h"
|
||||
#include "intf/i2c/ssd1306_i2c.h"
|
||||
#include "intf/ssd1306_interface.h"
|
||||
#include "intf/spi/ssd1306_spi_conf.h"
|
||||
#include "intf/spi/ssd1306_spi.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#if !defined(SDL_EMULATION)
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/i2c-dev.h>
|
||||
#include <stdlib.h>
|
||||
#include <linux/spi/spidev.h>
|
||||
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// MINGW I2C IMPLEMENTATION
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
#if defined(CONFIG_PLATFORM_I2C_AVAILABLE) && defined(CONFIG_PLATFORM_I2C_ENABLE)
|
||||
|
||||
#if !defined(SDL_EMULATION)
|
||||
|
||||
static uint8_t s_sa = SSD1306_SA;
|
||||
static int s_fd = -1;
|
||||
static uint8_t s_buffer[128];
|
||||
static uint8_t s_dataSize = 0;
|
||||
|
||||
static void platform_i2c_start(void)
|
||||
{
|
||||
s_dataSize = 0;
|
||||
}
|
||||
|
||||
static void platform_i2c_stop(void)
|
||||
{
|
||||
if (write(s_fd, s_buffer, s_dataSize) != s_dataSize)
|
||||
{
|
||||
fprintf(stderr, "Failed to write to the i2c bus: %s.\n", strerror(errno));
|
||||
}
|
||||
s_dataSize = 0;
|
||||
}
|
||||
|
||||
static void platform_i2c_send(uint8_t data)
|
||||
{
|
||||
s_buffer[s_dataSize] = data;
|
||||
s_dataSize++;
|
||||
if (s_dataSize == sizeof(s_buffer))
|
||||
{
|
||||
/* Send function puts all data to internal buffer. *
|
||||
* Restart transmission if internal buffer is full. */
|
||||
ssd1306_intf.stop();
|
||||
ssd1306_intf.start();
|
||||
ssd1306_intf.send(0x40);
|
||||
}
|
||||
}
|
||||
|
||||
static void platform_i2c_send_buffer(const uint8_t *buffer, uint16_t size)
|
||||
{
|
||||
while (size--)
|
||||
{
|
||||
platform_i2c_send(*buffer);
|
||||
buffer++;
|
||||
}
|
||||
}
|
||||
|
||||
static void platform_i2c_close()
|
||||
{
|
||||
if (s_fd >= 0)
|
||||
{
|
||||
close(s_fd);
|
||||
s_fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
static void empty_function()
|
||||
{
|
||||
}
|
||||
|
||||
static void empty_function_single_arg(uint8_t arg)
|
||||
{
|
||||
}
|
||||
|
||||
static void empty_function_two_args(const uint8_t *arg1, uint16_t arg2)
|
||||
{
|
||||
}
|
||||
|
||||
void ssd1306_platform_i2cInit(int8_t busId, uint8_t sa, ssd1306_platform_i2cConfig_t * cfg)
|
||||
{
|
||||
char filename[20];
|
||||
if (busId < 0)
|
||||
{
|
||||
busId = 1;
|
||||
}
|
||||
snprintf(filename, 19, "/dev/i2c-%d", busId);
|
||||
ssd1306_intf.start = empty_function;
|
||||
ssd1306_intf.stop = empty_function;
|
||||
ssd1306_intf.close = empty_function;
|
||||
ssd1306_intf.send = empty_function_single_arg;
|
||||
ssd1306_intf.send_buffer = empty_function_two_args;
|
||||
if ((s_fd = open(filename, O_RDWR)) < 0)
|
||||
{
|
||||
fprintf(stderr, "Failed to open the i2c bus\n");
|
||||
return;
|
||||
}
|
||||
if (sa)
|
||||
{
|
||||
s_sa = sa;
|
||||
}
|
||||
if (ioctl(s_fd, I2C_SLAVE, s_sa) < 0)
|
||||
{
|
||||
fprintf(stderr, "Failed to acquire bus access and/or talk to slave.\n");
|
||||
return;
|
||||
}
|
||||
ssd1306_intf.start = platform_i2c_start;
|
||||
ssd1306_intf.stop = platform_i2c_stop;
|
||||
ssd1306_intf.send = platform_i2c_send;
|
||||
ssd1306_intf.send_buffer = platform_i2c_send_buffer;
|
||||
ssd1306_intf.close = platform_i2c_close;
|
||||
}
|
||||
|
||||
#else /* SDL_EMULATION */
|
||||
|
||||
#include "sdl_core.h"
|
||||
|
||||
static void platform_i2c_send_buffer(const uint8_t *buffer, uint16_t size)
|
||||
{
|
||||
while (size--)
|
||||
{
|
||||
sdl_send_byte(*buffer);
|
||||
buffer++;
|
||||
};
|
||||
}
|
||||
|
||||
void ssd1306_platform_i2cInit(int8_t busId, uint8_t sa, ssd1306_platform_i2cConfig_t * cfg)
|
||||
{
|
||||
sdl_core_init();
|
||||
ssd1306_intf.spi = 0;
|
||||
ssd1306_intf.start = sdl_send_init;
|
||||
ssd1306_intf.stop = sdl_send_stop;
|
||||
ssd1306_intf.send = sdl_send_byte;
|
||||
ssd1306_intf.send_buffer = platform_i2c_send_buffer;
|
||||
ssd1306_intf.close = sdl_core_close;
|
||||
}
|
||||
|
||||
#endif /* SDL_EMULATION */
|
||||
|
||||
#endif // CONFIG_PLATFORM_I2C_AVAILABLE
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// MINGW SPI IMPLEMENTATION
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
#if defined(CONFIG_PLATFORM_SPI_AVAILABLE) && defined(CONFIG_PLATFORM_SPI_ENABLE)
|
||||
|
||||
#if !defined(SDL_EMULATION)
|
||||
|
||||
static int s_spi_fd = -1;
|
||||
extern uint32_t s_ssd1306_spi_clock;
|
||||
|
||||
static void platform_spi_start(void)
|
||||
{
|
||||
}
|
||||
|
||||
static void platform_spi_stop(void)
|
||||
{
|
||||
}
|
||||
|
||||
static void platform_spi_send(uint8_t data)
|
||||
{
|
||||
/* TODO: Yeah, sending single bytes is too slow, but *
|
||||
* need to figure out how to detect data/command bytes *
|
||||
* to send bytes as one block */
|
||||
uint8_t buf[1];
|
||||
struct spi_ioc_transfer mesg;
|
||||
buf[0] = data;
|
||||
memset(&mesg, 0, sizeof mesg);
|
||||
mesg.tx_buf = (unsigned long)&buf[0];
|
||||
mesg.rx_buf = 0;
|
||||
mesg.len = 1;
|
||||
mesg.delay_usecs = 0;
|
||||
mesg.speed_hz = 0;
|
||||
mesg.bits_per_word = 8;
|
||||
mesg.cs_change = 0;
|
||||
if (ioctl(s_spi_fd, SPI_IOC_MESSAGE(1), &mesg) < 1)
|
||||
{
|
||||
fprintf(stderr, "SPI failed to send SPI message: %s\n", strerror (errno)) ;
|
||||
}
|
||||
}
|
||||
|
||||
static void platform_spi_close(void)
|
||||
{
|
||||
if (s_spi_fd >= 0)
|
||||
{
|
||||
close(s_spi_fd);
|
||||
s_spi_fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
static void platform_spi_send_buffer(const uint8_t *data, uint16_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
platform_spi_send(*data);
|
||||
data++;
|
||||
}
|
||||
}
|
||||
|
||||
static void empty_function_spi(void)
|
||||
{
|
||||
}
|
||||
|
||||
static void empty_function_arg_spi(uint8_t byte)
|
||||
{
|
||||
}
|
||||
|
||||
static void empty_function_args_spi(const uint8_t *buffer, uint16_t bytes)
|
||||
{
|
||||
}
|
||||
|
||||
void ssd1306_platform_spiInit(int8_t busId,
|
||||
int8_t ces,
|
||||
int8_t dcPin)
|
||||
{
|
||||
char filename[20];
|
||||
if (busId < 0)
|
||||
{
|
||||
busId = 0;
|
||||
}
|
||||
if (ces < 0)
|
||||
{
|
||||
ces = 0;
|
||||
}
|
||||
s_ssd1306_cs = -1; // SPI interface does't need separate ces pin
|
||||
s_ssd1306_dc = dcPin;
|
||||
ssd1306_intf.spi = 1;
|
||||
ssd1306_intf.start = empty_function_spi;
|
||||
ssd1306_intf.stop = empty_function_spi;
|
||||
ssd1306_intf.send = empty_function_arg_spi;
|
||||
ssd1306_intf.send_buffer = empty_function_args_spi;
|
||||
ssd1306_intf.close = empty_function;
|
||||
|
||||
snprintf(filename, 19, "/dev/spidev%d.%d", busId, ces);
|
||||
if ((s_spi_fd = open(filename, O_RDWR)) < 0)
|
||||
{
|
||||
printf("Failed to initialize SPI: %s!\n", strerror(errno));
|
||||
return;
|
||||
}
|
||||
unsigned int speed = s_ssd1306_spi_clock;
|
||||
if (ioctl(s_spi_fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed) < 0)
|
||||
{
|
||||
printf("Failed to set speed on SPI line: %s!\n", strerror(errno));
|
||||
}
|
||||
uint8_t mode = SPI_MODE_0;
|
||||
if (ioctl (s_spi_fd, SPI_IOC_WR_MODE, &mode) < 0)
|
||||
{
|
||||
printf("Failed to set SPI mode: %s!\n", strerror(errno));
|
||||
}
|
||||
uint8_t spi_bpw = 8;
|
||||
if (ioctl (s_spi_fd, SPI_IOC_WR_BITS_PER_WORD, &spi_bpw) < 0)
|
||||
{
|
||||
printf("Failed to set SPI BPW: %s!\n", strerror(errno));
|
||||
}
|
||||
|
||||
ssd1306_intf.spi = 1;
|
||||
ssd1306_intf.start = platform_spi_start;
|
||||
ssd1306_intf.stop = platform_spi_stop;
|
||||
ssd1306_intf.send = platform_spi_send;
|
||||
ssd1306_intf.send_buffer = platform_spi_send_buffer;
|
||||
ssd1306_intf.close = platform_spi_close;
|
||||
}
|
||||
|
||||
#else /* SDL_EMULATION */
|
||||
|
||||
#include "sdl_core.h"
|
||||
|
||||
static void sdl_send_bytes(const uint8_t *buffer, uint16_t size)
|
||||
{
|
||||
while (size--)
|
||||
{
|
||||
sdl_send_byte(*buffer);
|
||||
buffer++;
|
||||
};
|
||||
}
|
||||
|
||||
void ssd1306_platform_spiInit(int8_t busId, int8_t ces, int8_t dcPin)
|
||||
{
|
||||
sdl_core_init();
|
||||
if (ces >= 0)
|
||||
{
|
||||
s_ssd1306_cs = ces;
|
||||
}
|
||||
if (dcPin >= 0)
|
||||
{
|
||||
s_ssd1306_dc = dcPin;
|
||||
}
|
||||
sdl_set_dc_pin(dcPin);
|
||||
ssd1306_intf.spi = 1;
|
||||
ssd1306_intf.start = sdl_send_init;
|
||||
ssd1306_intf.stop = sdl_send_stop;
|
||||
ssd1306_intf.send = sdl_send_byte;
|
||||
ssd1306_intf.send_buffer = sdl_send_bytes;
|
||||
ssd1306_intf.close = sdl_core_close;
|
||||
}
|
||||
|
||||
#endif /* SDL_EMULATION */
|
||||
|
||||
#endif // CONFIG_PLATFORM_SPI_AVAILABLE
|
||||
|
||||
#endif // __MINGW32__
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018, Alexey Dynda
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file ssd1306_hal/stm32/io.h This is stm32 platform file
|
||||
*/
|
||||
|
||||
#ifndef _SSD1306_STM32_IO_H_
|
||||
#define _SSD1306_STM32_IO_H_
|
||||
|
||||
// TODO: To add support. Any help is welcome
|
||||
|
||||
#define SSD1306_STM32_PLATFORM
|
||||
//========================== I. Include libraries =========================
|
||||
/* 1. Include all required headers, specific for your platform here */
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define LOW 0
|
||||
#define HIGH 1
|
||||
#define INPUT 0
|
||||
#define OUTPUT 1
|
||||
/* Progmem attribute for data, located in Flash */
|
||||
#define PROGMEM
|
||||
|
||||
//========================== II. Define options ===========================
|
||||
/* 2. Uncomment all options, you have support for on your platform *
|
||||
* Remember that you will need to implement low level intf/i2c or *
|
||||
* intf/spi layers for your platform */
|
||||
|
||||
/** The macro is defined when STM32 i2c implementation is available */
|
||||
#define CONFIG_PLATFORM_I2C_AVAILABLE
|
||||
#define CONFIG_PLATFORM_SPI_AVAILABLE
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//========================== III. Implement functions =====================
|
||||
/* Implement functions below the way you like. You can make them non-static */
|
||||
// !!! MANDATORY !!!
|
||||
static inline int digitalRead(int pin) // digitalRead()
|
||||
{
|
||||
return LOW;
|
||||
}
|
||||
|
||||
static inline void digitalWrite(int pin, int level) // digitalWrite()
|
||||
{
|
||||
}
|
||||
|
||||
static inline void pinMode(int pin, int mode) // pinMode()
|
||||
{
|
||||
}
|
||||
|
||||
static inline int analogRead(int pin) // analogRead()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline uint32_t millis(void) // millis()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline uint32_t micros(void) // micros()
|
||||
{
|
||||
return 0;
|
||||
};
|
||||
|
||||
static inline void delay(uint32_t ms) // delay()
|
||||
{
|
||||
}
|
||||
|
||||
static inline void delayMicroseconds(uint32_t us) // delayMicroseconds()
|
||||
{
|
||||
}
|
||||
|
||||
// !!! OPTIONAL !!!
|
||||
static inline void randomSeed(int seed) // randomSeed() - can be skipped
|
||||
{
|
||||
}
|
||||
|
||||
static inline void attachInterrupt(int pin, void (*interrupt)(), int level) // attachInterrupt() - can be skipped
|
||||
{
|
||||
}
|
||||
|
||||
static inline uint8_t pgm_read_byte(const void *ptr) // pgm_read_byte() - can be skipped
|
||||
{
|
||||
return *((const uint8_t *)ptr);
|
||||
}
|
||||
|
||||
static inline uint16_t eeprom_read_word(const void *ptr) // eeprom_read_word() - can be skipped
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void eeprom_write_word(const void *ptr, uint16_t val) // eeprom_write_word() - can be skipped
|
||||
{
|
||||
}
|
||||
|
||||
// utoa is already defined in stdlib c
|
||||
//static inline char *utoa(unsigned int num, char *str, int radix) // util utoa() - can be skipped
|
||||
//{
|
||||
// *str = '\0';
|
||||
// return str;
|
||||
//}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
static inline int random(int max) // random(n) - can be skipped if you don't use it
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int random(int min, int max) // random(a,b) - can be skipped if you don't use it
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018, Alexey Dynda
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "ssd1306_hal/io.h"
|
||||
|
||||
#if defined(SSD1306_STM32_PLATFORM)
|
||||
|
||||
#include "intf/ssd1306_interface.h"
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
// TODO: To add support. Any help is welcome
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// !!! PLATFORM I2C IMPLEMENTATION OPTIONAL !!!
|
||||
#if defined(CONFIG_PLATFORM_I2C_AVAILABLE) && defined(CONFIG_PLATFORM_I2C_ENABLE)
|
||||
static uint8_t s_i2c_addr = 0x3C;
|
||||
|
||||
static void platform_i2c_start(void)
|
||||
{
|
||||
// ... Open i2c channel for your device with specific s_i2c_addr
|
||||
}
|
||||
|
||||
static void platform_i2c_stop(void)
|
||||
{
|
||||
// ... Complete i2c communication
|
||||
}
|
||||
|
||||
static void platform_i2c_send(uint8_t data)
|
||||
{
|
||||
// ... Send byte to i2c communication channel
|
||||
}
|
||||
|
||||
static void platform_i2c_close(void)
|
||||
{
|
||||
// ... free all i2c resources here
|
||||
}
|
||||
|
||||
static void platform_i2c_send_buffer(const uint8_t *data, uint16_t len)
|
||||
{
|
||||
// ... Send len bytes to i2c communication channel here
|
||||
}
|
||||
|
||||
void ssd1306_platform_i2cInit(int8_t busId, uint8_t addr, ssd1306_platform_i2cConfig_t * cfg)
|
||||
{
|
||||
if (addr) s_i2c_addr = addr;
|
||||
if (HAL_I2C_IsDeviceReady(&hi2c1, s_i2c_addr, 1, 20000) != HAL_OK)
|
||||
{
|
||||
return;
|
||||
}
|
||||
ssd1306_intf.spi = 0;
|
||||
ssd1306_intf.start = &platform_i2c_start;
|
||||
ssd1306_intf.stop = &platform_i2c_stop;
|
||||
ssd1306_intf.send = &platform_i2c_send;
|
||||
ssd1306_intf.close = &platform_i2c_close;
|
||||
ssd1306_intf.send_buffer = &platform_i2c_send_buffer;
|
||||
// init your interface here
|
||||
//...
|
||||
}
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// !!! PLATFORM SPI IMPLEMENTATION OPTIONAL !!!
|
||||
#if defined(CONFIG_PLATFORM_SPI_AVAILABLE) && defined(CONFIG_PLATFORM_SPI_ENABLE)
|
||||
|
||||
#include "intf/spi/ssd1306_spi.h"
|
||||
|
||||
static void platform_spi_start(void)
|
||||
{
|
||||
// ... Open spi channel for your device with specific s_ssd1306_cs, s_ssd1306_dc
|
||||
}
|
||||
|
||||
static void platform_spi_stop(void)
|
||||
{
|
||||
// ... Complete spi communication
|
||||
}
|
||||
|
||||
static void platform_spi_send(uint8_t data)
|
||||
{
|
||||
// ... Send byte to spi communication channel
|
||||
}
|
||||
|
||||
static void platform_spi_close(void)
|
||||
{
|
||||
// ... free all spi resources here
|
||||
}
|
||||
|
||||
static void platform_spi_send_buffer(const uint8_t *data, uint16_t len)
|
||||
{
|
||||
// ... Send len bytes to spi communication channel here
|
||||
}
|
||||
|
||||
void ssd1306_platform_spiInit(int8_t busId,
|
||||
int8_t cesPin,
|
||||
int8_t dcPin)
|
||||
{
|
||||
if (cesPin>=0) s_ssd1306_cs = cesPin;
|
||||
if (dcPin>=0) s_ssd1306_dc = dcPin;
|
||||
ssd1306_intf.spi = 1;
|
||||
ssd1306_intf.start = &platform_spi_start;
|
||||
ssd1306_intf.stop = &platform_spi_stop;
|
||||
ssd1306_intf.send = &platform_spi_send;
|
||||
ssd1306_intf.close = &platform_spi_close;
|
||||
ssd1306_intf.send_buffer = &platform_spi_send_buffer;
|
||||
// init your interface here
|
||||
//...
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // YOUR_PLATFORM
|
||||
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018, Alexey Dynda
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file ssd1306_hal/template/io.h This is template file for new platform with detailed instructions
|
||||
*/
|
||||
|
||||
#ifndef _SSD1306_YOUR_PLATFORM_IO_H_
|
||||
#define _SSD1306_YOUR_PLATFORM_IO_H_
|
||||
|
||||
//========================== I. Create directory for your platform ========
|
||||
/* 1. Copy content of this folder to src/ssd1306_hal/<your_platform>/ folder */
|
||||
/* 2. Replace YOUR_PLATFORM in these files with the one, you would like to use */
|
||||
/* 3. Add #include "<your_platform>/io.h" to src/ssd1306_hal/io.h file */
|
||||
/* (remember to add required #elif defined(X) lines) */
|
||||
/* 4. Add platform.c file to SOURCES list in src/Makefile.src */
|
||||
/* 5. Implement functions below and functions in platform.c file */
|
||||
|
||||
#define YOUR_PLATFORM
|
||||
//========================== I. Include libraries =========================
|
||||
/* 1. Include all required headers, specific for your platform here */
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* If your platform already has these definitions, comment out lines below */
|
||||
#define LOW 0
|
||||
#define HIGH 1
|
||||
#define INPUT 0
|
||||
#define OUTPUT 1
|
||||
/* Progmem attribute for data, located in Flash */
|
||||
#define PROGMEM
|
||||
|
||||
//========================== II. Define options ===========================
|
||||
/* 2. Uncomment all options, you have support for on your platform *
|
||||
* Remember that you will need to implement low level intf/i2c or *
|
||||
* intf/spi layers for your platform */
|
||||
|
||||
//#define CONFIG_SOFTWARE_I2C_AVAILABLE
|
||||
//#define CONFIG_TWI_I2C_AVAILABLE
|
||||
//#define CONFIG_AVR_SPI_AVAILABLE
|
||||
//#define CONFIG_AVR_UART_AVAILABLE
|
||||
//#define CONFIG_VGA_AVAILABLE
|
||||
//#define CONFIG_PLATFORM_I2C_AVAILABLE
|
||||
//#define CONFIG_PLATFORM_SPI_AVAILABLE
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//========================== III. Implement functions =====================
|
||||
/* Implement functions below the way you like. You can make them non-static
|
||||
* and implement the functions in platform.c file
|
||||
*/
|
||||
// !!! MANDATORY. The library will not work without these functions !!!
|
||||
static inline int digitalRead(int pin) // digitalRead()
|
||||
{
|
||||
return LOW;
|
||||
}
|
||||
|
||||
static inline void digitalWrite(int pin, int level) // digitalWrite()
|
||||
{
|
||||
}
|
||||
|
||||
static inline void pinMode(int pin, int mode) // pinMode()
|
||||
{
|
||||
}
|
||||
|
||||
static inline int analogRead(int pin) // analogRead()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline uint32_t millis(void) // millis()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline uint32_t micros(void) // micros()
|
||||
{
|
||||
return 0;
|
||||
};
|
||||
|
||||
static inline void delay(uint32_t ms) // delay()
|
||||
{
|
||||
}
|
||||
|
||||
static inline void delayMicroseconds(uint32_t us) // delayMicroseconds()
|
||||
{
|
||||
}
|
||||
|
||||
// !!! OPTIONAL !!!
|
||||
static inline void randomSeed(int seed) // randomSeed() - can be skipped
|
||||
{
|
||||
}
|
||||
|
||||
static inline void attachInterrupt(int pin, void (*interrupt)(), int level) // attachInterrupt() - can be skipped
|
||||
{
|
||||
}
|
||||
|
||||
static inline uint8_t pgm_read_byte(const void *ptr) // pgm_read_byte() - can be left as is
|
||||
{
|
||||
return *((const uint8_t *)ptr);
|
||||
}
|
||||
|
||||
static inline uint16_t eeprom_read_word(const void *ptr) // eeprom_read_word() - can be skipped
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void eeprom_write_word(const void *ptr, uint16_t val) // eeprom_write_word() - can be skipped
|
||||
{
|
||||
}
|
||||
|
||||
static inline char *utoa(unsigned int num, char *str, int radix) // util utoa() - can be skipped
|
||||
{
|
||||
*str = '\0';
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
// !!! PLATFORM I2C IMPLEMENTATION OPTIONAL !!!
|
||||
#if defined(CONFIG_PLATFORM_I2C_AVAILABLE) && defined(CONFIG_PLATFORM_I2C_ENABLE)
|
||||
void ssd1306_platform_i2cInit(int8_t busId, uint8_t addr, ssd1306_platform_i2cConfig_t * cfg);
|
||||
#endif
|
||||
|
||||
|
||||
// !!! PLATFORM SPI IMPLEMENTATION OPTIONAL !!!
|
||||
#if defined(CONFIG_PLATFORM_SPI_AVAILABLE) && defined(CONFIG_PLATFORM_SPI_ENABLE)
|
||||
void ssd1306_platform_spiInit(uint8_t busId,
|
||||
uint8_t cesPin,
|
||||
uint8_t dcPin);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
static inline int random(int max) // random(n) - can be skipped if you don't use it
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int random(int min, int max) // random(a,b) - can be skipped if you don't use it
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018, Alexey Dynda
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "ssd1306_hal/io.h"
|
||||
|
||||
// TODO: DON'T FORGET ADD YOUR PLATFORM FILE TO MAKEFILE
|
||||
|
||||
#if defined(YOUR_PLATFORM)
|
||||
|
||||
#include "intf/ssd1306_interface.h"
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// !!! PLATFORM I2C IMPLEMENTATION OPTIONAL !!!
|
||||
#if defined(CONFIG_PLATFORM_I2C_AVAILABLE) && defined(CONFIG_PLATFORM_I2C_ENABLE)
|
||||
static uint8_t s_i2c_addr = 0x3C;
|
||||
|
||||
static void platform_i2c_start(void)
|
||||
{
|
||||
// ... Open i2c channel for your device with specific s_i2c_addr
|
||||
}
|
||||
|
||||
static void platform_i2c_stop(void)
|
||||
{
|
||||
// ... Complete i2c communication
|
||||
}
|
||||
|
||||
static void platform_i2c_send(uint8_t data)
|
||||
{
|
||||
// ... Send byte to i2c communication channel
|
||||
}
|
||||
|
||||
static void platform_i2c_close(void)
|
||||
{
|
||||
// ... free all i2c resources here
|
||||
}
|
||||
|
||||
static void platform_i2c_send_buffer(const uint8_t *data, uint16_t len)
|
||||
{
|
||||
// ... Send len bytes to i2c communication channel here
|
||||
}
|
||||
|
||||
void ssd1306_platform_i2cInit(int8_t busId, uint8_t addr, ssd1306_platform_i2cConfig_t * cfg)
|
||||
{
|
||||
if (addr) s_i2c_addr = addr;
|
||||
ssd1306_intf.spi = 0;
|
||||
ssd1306_intf.start = &platform_i2c_start;
|
||||
ssd1306_intf.stop = &platform_i2c_stop;
|
||||
ssd1306_intf.send = &platform_i2c_send;
|
||||
ssd1306_intf.close = &platform_i2c_close;
|
||||
ssd1306_intf.send_buffer = &platform_i2c_send_buffer;
|
||||
// init your interface here
|
||||
//...
|
||||
}
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// !!! PLATFORM SPI IMPLEMENTATION OPTIONAL !!!
|
||||
#if defined(CONFIG_PLATFORM_SPI_AVAILABLE) && defined(CONFIG_PLATFORM_SPI_ENABLE)
|
||||
|
||||
#include "intf/spi/ssd1306_spi.h"
|
||||
|
||||
static void platform_spi_start(void)
|
||||
{
|
||||
// ... Open spi channel for your device with specific s_ssd1306_cs, s_ssd1306_dc
|
||||
}
|
||||
|
||||
static void platform_spi_stop(void)
|
||||
{
|
||||
// ... Complete spi communication
|
||||
}
|
||||
|
||||
static void platform_spi_send(uint8_t data)
|
||||
{
|
||||
// ... Send byte to spi communication channel
|
||||
}
|
||||
|
||||
static void platform_spi_close(void)
|
||||
{
|
||||
// ... free all spi resources here
|
||||
}
|
||||
|
||||
static void platform_spi_send_buffer(const uint8_t *data, uint16_t len)
|
||||
{
|
||||
// ... Send len bytes to spi communication channel here
|
||||
}
|
||||
|
||||
void ssd1306_platform_spiInit(int8_t busId,
|
||||
int8_t cesPin,
|
||||
int8_t dcPin)
|
||||
{
|
||||
if (cesPin>=0) s_ssd1306_cs = cesPin;
|
||||
if (dcPin>=0) s_ssd1306_dc = dcPin;
|
||||
ssd1306_intf.spi = 1;
|
||||
ssd1306_intf.start = &platform_spi_start;
|
||||
ssd1306_intf.stop = &platform_spi_stop;
|
||||
ssd1306_intf.send = &platform_spi_send;
|
||||
ssd1306_intf.close = &platform_spi_close;
|
||||
ssd1306_intf.send_buffer = &platform_spi_send_buffer;
|
||||
// init your interface here
|
||||
//...
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // YOUR_PLATFORM
|
||||
Reference in New Issue
Block a user