This commit is contained in:
2022-10-30 23:00:53 +01:00
commit 7f087ae854
226 changed files with 27881 additions and 0 deletions
@@ -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
+14
View File
@@ -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
+225
View File
@@ -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 @@
+117
View File
@@ -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
+176
View File
@@ -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
+135
View File
@@ -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
+136
View File
@@ -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 @@
+168
View File
@@ -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__
+132
View File
@@ -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__
+147
View File
@@ -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