init git repo
This commit is contained in:
commit
2cbccd5599
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
build/
|
||||
.vscode/
|
||||
managed_components/
|
||||
dependencies.lock
|
||||
sdkconfig.old
|
||||
6
CMakeLists.txt
Executable file
6
CMakeLists.txt
Executable file
@ -0,0 +1,6 @@
|
||||
# The following lines of boilerplate have to be in your project's
|
||||
# CMakeLists in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(blk_box_full_test_5)
|
||||
53
README.md
Executable file
53
README.md
Executable file
@ -0,0 +1,53 @@
|
||||
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | Linux |
|
||||
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | ----- |
|
||||
|
||||
# Hello World Example
|
||||
|
||||
Starts a FreeRTOS task to print "Hello World".
|
||||
|
||||
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
||||
|
||||
## How to use example
|
||||
|
||||
Follow detailed instructions provided specifically for this example.
|
||||
|
||||
Select the instructions depending on Espressif chip installed on your development board:
|
||||
|
||||
- [ESP32 Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/stable/get-started/index.html)
|
||||
- [ESP32-S2 Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/get-started/index.html)
|
||||
|
||||
|
||||
## Example folder contents
|
||||
|
||||
The project **hello_world** contains one source file in C language [hello_world_main.c](main/hello_world_main.c). The file is located in folder [main](main).
|
||||
|
||||
ESP-IDF projects are built using CMake. The project build configuration is contained in `CMakeLists.txt` files that provide set of directives and instructions describing the project's source files and targets (executable, library, or both).
|
||||
|
||||
Below is short explanation of remaining files in the project folder.
|
||||
|
||||
```
|
||||
├── CMakeLists.txt
|
||||
├── pytest_hello_world.py Python script used for automated testing
|
||||
├── main
|
||||
│ ├── CMakeLists.txt
|
||||
│ └── hello_world_main.c
|
||||
└── README.md This is the file you are currently reading
|
||||
```
|
||||
|
||||
For more information on structure and contents of ESP-IDF projects, please refer to Section [Build System](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/build-system.html) of the ESP-IDF Programming Guide.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
* Program upload failure
|
||||
|
||||
* Hardware connection is not correct: run `idf.py -p PORT monitor`, and reboot your board to see if there are any output logs.
|
||||
* The baud rate for downloading is too high: lower your baud rate in the `menuconfig` menu, and try again.
|
||||
|
||||
## Technical support and feedback
|
||||
|
||||
Please use the following feedback channels:
|
||||
|
||||
* For technical queries, go to the [esp32.com](https://esp32.com/) forum
|
||||
* For a feature request or bug report, create a [GitHub issue](https://github.com/espressif/esp-idf/issues)
|
||||
|
||||
We will get back to you as soon as possible.
|
||||
2
main/CMakeLists.txt
Executable file
2
main/CMakeLists.txt
Executable file
@ -0,0 +1,2 @@
|
||||
idf_component_register(SRCS "main.cpp" "drivers/TM1640/TM16xx.cpp" "drivers/TM1640/TM1640.cpp"
|
||||
INCLUDE_DIRS "")
|
||||
61
main/drivers/TM1640/TM1640.cpp
Normal file
61
main/drivers/TM1640/TM1640.cpp
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
TM1640.cpp - Library implementation for TM1640.
|
||||
|
||||
Copyright (C) 2011 Ricardo Batista (rjbatista <at> gmail <dot> com)
|
||||
Adjusted for TM1640 by Maxint R&D, based on orignal code. See https://github.com/maxint-rd/
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the version 3 GNU General Public License as
|
||||
published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "TM1640.h"
|
||||
#include <stdint.h>
|
||||
#include <driver/gpio.h>
|
||||
|
||||
TM1640::TM1640(gpio_num_t dataPin, gpio_num_t clockPin, uint8_t numDigits, bool activateDisplay, uint8_t intensity)
|
||||
: TM16xx(dataPin, clockPin, dataPin, TM1640_MAX_POS, numDigits, activateDisplay, intensity)
|
||||
{ // NOTE: Like the TM1637, the TM1640 only has DIO and CLK. Therefor the DIO-pin is initialized as strobe in the constructor
|
||||
clearDisplay();
|
||||
setupDisplay(activateDisplay, intensity);
|
||||
}
|
||||
|
||||
/*
|
||||
void TM1640::bitDelay()
|
||||
{
|
||||
//delayMicroseconds(5);
|
||||
}
|
||||
*/
|
||||
|
||||
void TM1640::start()
|
||||
{ // if needed derived classes can use different patterns to start a command (eg. for TM1637)
|
||||
// Datasheet: The starting condition of data input is: when CLK is high, the DIN becomes low from high;
|
||||
gpio_set_level(dataPin, 0);
|
||||
gpio_set_level(clockPin, 0);
|
||||
bitDelay();
|
||||
}
|
||||
|
||||
void TM1640::stop()
|
||||
{ // if needed derived classes can use different patterns to stop a command (eg. for TM1637)
|
||||
// datasheet: the ending condition is: when CLK is high, the DIN becomes high from low.
|
||||
gpio_set_level(clockPin, 1);
|
||||
gpio_set_level(dataPin, 1);
|
||||
bitDelay();
|
||||
}
|
||||
|
||||
void TM1640::send(uint8_t data)
|
||||
{
|
||||
// MOLE 180514: TM1640 wants data and clock to be low after sending the data
|
||||
TM16xx::send(data);
|
||||
gpio_set_level(clockPin, 0); // first clock low
|
||||
gpio_set_level(dataPin, 0); // then data low
|
||||
bitDelay();
|
||||
}
|
||||
41
main/drivers/TM1640/TM1640.h
Normal file
41
main/drivers/TM1640/TM1640.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
TM1640.h - Library for TM1640.
|
||||
|
||||
Copyright (C) 2011 Ricardo Batista <rjbatista at gmail dot com>
|
||||
Adjusted for TM1640 by Maxint R&D, based on orignal code. See https://github.com/maxint-rd/
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the version 3 GNU General Public License as
|
||||
published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TM1640_h
|
||||
#define TM1640_h
|
||||
|
||||
#include "TM16xx.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#define TM1640_MAX_POS 16
|
||||
|
||||
class TM1640 : public TM16xx
|
||||
{
|
||||
public:
|
||||
// Instantiate a TM1640 module specifying data and clock pins, number of digits, the display state, the starting intensity (0-7).
|
||||
TM1640(gpio_num_t dataPin, gpio_num_t clockPin, uint8_t numDigits=16, bool activateDisplay = true, uint8_t intensity = 7);
|
||||
|
||||
protected:
|
||||
//virtual void bitDelay();
|
||||
virtual void start();
|
||||
virtual void stop();
|
||||
virtual void send(uint8_t data);
|
||||
};
|
||||
|
||||
#endif
|
||||
262
main/drivers/TM1640/TM16xx.cpp
Normal file
262
main/drivers/TM1640/TM16xx.cpp
Normal file
@ -0,0 +1,262 @@
|
||||
/*
|
||||
TM16xx.h - Library for TM1637, TM1638 and similar chips.
|
||||
Modified by Maxint R&D. See https://github.com/maxint-rd/
|
||||
|
||||
Copyright (C) 2011 Ricardo Batista (rjbatista <at> gmail <dot> com)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the version 3 GNU General Public License as
|
||||
published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "TM16xx.h"
|
||||
#include <driver/gpio.h>
|
||||
|
||||
TM16xx::TM16xx(gpio_num_t dataPin, gpio_num_t clockPin, gpio_num_t strobePin, uint8_t maxDisplays, uint8_t nDigitsUsed, bool activateDisplay, uint8_t intensity)
|
||||
{
|
||||
this->dataPin = dataPin;
|
||||
this->clockPin = clockPin;
|
||||
this->strobePin = strobePin;
|
||||
this->_maxDisplays = maxDisplays;
|
||||
this->digits = nDigitsUsed;
|
||||
|
||||
gpio_set_direction(dataPin, GPIO_MODE_OUTPUT);
|
||||
gpio_set_direction(clockPin, GPIO_MODE_OUTPUT);
|
||||
gpio_set_direction(strobePin, GPIO_MODE_OUTPUT);
|
||||
|
||||
gpio_set_level(strobePin, 1);
|
||||
gpio_set_level(clockPin, 1);
|
||||
|
||||
//sendCommand(TM16XX_CMD_DISPLAY | (activateDisplay ? 8 : 0) | min(7, intensity)); // display command: on or intensity
|
||||
|
||||
/*
|
||||
sendCommand(TM16XX_CMD_DATA_AUTO); // data command: set data mode to auto-increment write mode
|
||||
start();
|
||||
send(TM16XX_CMD_ADDRESS); // address command + address C0H
|
||||
for (int i = 0; i < 16; i++) { // TM1638 and TM1640 have 16 data addresses, TM1637 and TM1668 have less, but will wrap.
|
||||
send(0x00);
|
||||
}
|
||||
stop();
|
||||
*/
|
||||
// Note: calling these methods should be done in constructor of derived class in order to use properly initialized members!
|
||||
/*
|
||||
clearDisplay();
|
||||
setupDisplay(activateDisplay, intensity);
|
||||
*/
|
||||
}
|
||||
|
||||
void TM16xx::setupDisplay(bool active, uint8_t intensity)
|
||||
{
|
||||
sendCommand(TM16XX_CMD_DISPLAY | (active ? 8 : 0) | min(7, intensity));
|
||||
}
|
||||
|
||||
void TM16xx::clearDisplay()
|
||||
{ // Clear all data registers. The number of registers depends on the chip.
|
||||
// TM1638 (10x8): 10 segments per grid, stored in two bytes. The first byte contains the first 8 display segments, second byte has seg9+seg10 => 16 bytes
|
||||
// TM1640 (8x16): one byte per grid => 16 bytes
|
||||
// TM1637 (8x6): one byte per grid => 6 bytes
|
||||
// TM1668 (10x7 - 14x3): two bytes per grid => 14 bytes
|
||||
sendCommand(TM16XX_CMD_DATA_AUTO); // set auto increment addressing mode
|
||||
|
||||
// send the address followed by bulk-sending of the data to clear the display memory
|
||||
start();
|
||||
send(TM16XX_CMD_ADDRESS);
|
||||
for (int i = 0; i < _maxDisplays; i++) {
|
||||
send(0x00);
|
||||
if(_maxSegments>8)
|
||||
send(0x00); // send second byte (applicable to TM1638 and TM1668)
|
||||
}
|
||||
stop();
|
||||
|
||||
}
|
||||
|
||||
void TM16xx::setSegments(uint8_t segments, uint8_t position)
|
||||
{ // set 8 leds on common grd as specified
|
||||
// TODO: support 10-14 segments on chips like TM1638/TM1668
|
||||
if(position<_maxDisplays)
|
||||
sendData(position, segments);
|
||||
//sendData(TM16XX_CMD_ADDRESS | position, segments);
|
||||
}
|
||||
|
||||
void TM16xx::setSegments16(uint16_t segments, uint8_t position)
|
||||
{ // Some modules support more than 8 segments (e.g. 10 max for TM1638)
|
||||
// The position of the additional segments in the second data byte can be different per module,
|
||||
// For that reason this module has no implementation in the base class.
|
||||
// E.g. for TM1638/TM1668 segments 8-9 are in bits 0-1, for TM1630 segment 14 is in bit 5
|
||||
// This method assumes segments 0-7 to be in the lower byte and the extra segments in the upper byte
|
||||
// Depending on the module this method should shift the segments to the proper data position.
|
||||
}
|
||||
|
||||
|
||||
void TM16xx::sendChar(uint8_t pos, uint8_t data, bool dot)
|
||||
{
|
||||
/*
|
||||
if(pos<_maxDisplays)
|
||||
sendData(pos, data | (dot ? 0b10000000 : 0));
|
||||
*/
|
||||
setSegments(data | (dot ? 0b10000000 : 0), pos);
|
||||
}
|
||||
|
||||
void TM16xx::sendAsciiChar(uint8_t pos, char c, bool fDot)
|
||||
{ // Method to send an Ascii character to the display
|
||||
// This method is also called by TM16xxDisplay.print to display characters
|
||||
// The base class uses the default 7-segment font to find the LED pattern.
|
||||
// Derived classes for multi-segment displays or alternate layout displays can override this method
|
||||
sendChar(pos, TM16XX_FONT_DEFAULT[c-32], fDot);
|
||||
}
|
||||
|
||||
|
||||
void TM16xx::setDisplayDigit(uint8_t digit, uint8_t pos, bool dot, const uint8_t numberFont[])
|
||||
{
|
||||
sendChar(pos, numberFont[digit & 0xF], dot);
|
||||
}
|
||||
|
||||
void TM16xx::setDisplayToDecNumber(int nNumber, uint8_t bDots) // byte bDots=0
|
||||
{ // Function to display a decimal number on a n-digit clock display.
|
||||
// Kept simple to fit in ATtiny44A
|
||||
// For extended display features use the TM16xxDisplay class
|
||||
|
||||
// TODO: support large displays such as 8segx16 on TM1640
|
||||
for(uint8_t nPos=1; nPos<=digits; nPos++)
|
||||
{
|
||||
setDisplayDigit(nNumber % 10, digits - nPos, bDots&_BV(nPos));
|
||||
nNumber/=10;
|
||||
}
|
||||
}
|
||||
|
||||
void TM16xx::clearDisplayDigit(uint8_t pos, bool dot)
|
||||
{
|
||||
sendChar(pos, 0, dot);
|
||||
}
|
||||
|
||||
void TM16xx::setDisplay(const uint8_t values[], uint8_t size)
|
||||
{ // send an array of values to the display
|
||||
for (uint8_t i = 0; i < size; i++) {
|
||||
sendChar(i, values[i], 0);
|
||||
}
|
||||
}
|
||||
|
||||
void TM16xx::setDisplayToString(const char* string, const uint32_t dots, const uint8_t pos, const uint8_t font[])
|
||||
{
|
||||
for (int i = 0; i < digits - pos; i++) {
|
||||
if (string[i] != '\0') {
|
||||
//sendChar(i + pos, pgm_read_byte_near(font+(string[i] - 32)), (dots & (1 << (digits - i - 1))) != 0);
|
||||
sendAsciiChar(i + pos, string[i], (dots & (1 << (digits - i - 1))) != 0);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t TM16xx::getNumDigits()
|
||||
{ // get the number of digits used (needed by TM16xxDisplay to combine modules)
|
||||
return(digits);
|
||||
}
|
||||
|
||||
// key-scanning method, implemented in chip specific derived class
|
||||
uint32_t TM16xx::getButtons()
|
||||
{ // return state of up to 32 keys.
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Protected methods
|
||||
//
|
||||
|
||||
void TM16xx::bitDelay()
|
||||
{ // if needed derived classes can add a delay (eg. for TM1637)
|
||||
//delayMicroseconds(50);
|
||||
|
||||
// On fast MCUs like ESP32 a delay is required, especially when reading buttons
|
||||
// The TM1638 datasheet specifies a max clock speed of 1MHz.
|
||||
// Testing shows that without delay the CLK line exceeds 1.6 MHz on the ESP32. While displaying data still worked, reading buttons failed.
|
||||
// Adding a 1us delay gives clockpulses of about 1.75us-2.0us (~ 250kHz) on an ESP32 @240MHz and a similar delay on an ESP8266 @160Mhz.
|
||||
// An ESP32 running without delay at 240MHz gave a CLK of ~0.3us (~ 1.6MHz)
|
||||
// An ESP8266 running without delay at 160MHz gave a CLK of ~0.9us (~ 470kHz)
|
||||
// An ESP8266 running without delay at 80MHz gave a CLK of ~1.8us (~ 240kHz)
|
||||
#if F_CPU>100000000
|
||||
delayMicroseconds(1);
|
||||
#endif
|
||||
}
|
||||
|
||||
void TM16xx::start()
|
||||
{ // if needed derived classes can use different patterns to start a command (eg. for TM1637)
|
||||
gpio_set_level(strobePin, 0);
|
||||
bitDelay();
|
||||
}
|
||||
|
||||
void TM16xx::stop()
|
||||
{ // if needed derived classes can use different patterns to stop a command (eg. for TM1637)
|
||||
gpio_set_level(strobePin, 1);
|
||||
bitDelay();
|
||||
}
|
||||
|
||||
void TM16xx::send(uint8_t data)
|
||||
{
|
||||
// MMOLE 180203: shiftout does something, but is not okay (tested on TM1668)
|
||||
//shiftOut(dataPin, clockPin, LSBFIRST, data);
|
||||
for (int i = 0; i < 8; i++) {
|
||||
gpio_set_level(clockPin, 0);
|
||||
bitDelay();
|
||||
gpio_set_level(dataPin, data & 1);
|
||||
bitDelay();
|
||||
data >>= 1;
|
||||
gpio_set_level(clockPin, 1);
|
||||
bitDelay();
|
||||
}
|
||||
bitDelay(); // NOTE: TM1638 specifies a Twait between bytes of minimal 1us.
|
||||
}
|
||||
|
||||
void TM16xx::sendCommand(uint8_t cmd)
|
||||
{
|
||||
start();
|
||||
send(cmd);
|
||||
stop();
|
||||
}
|
||||
|
||||
void TM16xx::sendData(uint8_t address, uint8_t data)
|
||||
{
|
||||
sendCommand(TM16XX_CMD_DATA_FIXED); // use fixed addressing for data
|
||||
start();
|
||||
send(TM16XX_CMD_ADDRESS | address); // address command + address
|
||||
send(data);
|
||||
stop();
|
||||
}
|
||||
|
||||
uint8_t TM16xx::receive()
|
||||
{
|
||||
uint8_t temp = 0;
|
||||
|
||||
// Pull-up on
|
||||
gpio_set_direction(dataPin, GPIO_MODE_INPUT);
|
||||
gpio_set_level(dataPin, 1);
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
temp >>= 1;
|
||||
|
||||
gpio_set_level(clockPin, 0);
|
||||
bitDelay(); // NOTE: on TM1637 reading keys should be slower than 250Khz (see datasheet p3)
|
||||
|
||||
if (gpio_get_level(dataPin)) {
|
||||
temp |= 0x80;
|
||||
}
|
||||
|
||||
gpio_set_level(clockPin, 1);
|
||||
bitDelay();
|
||||
}
|
||||
|
||||
// Pull-up off
|
||||
gpio_set_direction(dataPin, GPIO_MODE_OUTPUT);
|
||||
gpio_set_level(dataPin, 0);
|
||||
|
||||
return temp;
|
||||
}
|
||||
138
main/drivers/TM1640/TM16xx.h
Normal file
138
main/drivers/TM1640/TM16xx.h
Normal file
@ -0,0 +1,138 @@
|
||||
/*
|
||||
TM16xx.h - Library for TM1637, TM1638 and similar chips.
|
||||
|
||||
Copyright (C) 2011 Ricardo Batista <rjbatista at gmail dot com>
|
||||
Modified by Maxint R&D. See https://github.com/maxint-rd/
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the version 3 GNU General Public License as
|
||||
published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TM16XX_h
|
||||
#define TM16XX_h
|
||||
|
||||
#if !defined(__max)
|
||||
// MMOLE 180325: min, max are no macro in ESP core 2.3.9 libraries, see https://github.com/esp8266/Arduino/issues/398
|
||||
// MMOLE 211229: Redefining min/max has issues in newer ESP cores with certain wifi libraries.
|
||||
// See definition as function template below.
|
||||
#define __min(a,b) ((a)<(b)?(a):(b))
|
||||
#define __max(a,b) ((a)>(b)?(a):(b))
|
||||
#endif
|
||||
|
||||
#if !defined(_BV)
|
||||
// MMOLE 220909: _BV is not defined in Raspberry Pi Pico RP2040 core v2.4.0 or v2.5.2 by Earle F. Philhower
|
||||
// TM16xx uses it in some classes to determine button presses (TM1628/30/37/38/38Anode
|
||||
// Note that _BV works on int values (16-bit in Arduino). For that reason using bit() would be better.
|
||||
// This is how _BV is defined in the AVR libraries used within Arduino:
|
||||
#define _BV( x )( 1<<(x))
|
||||
#endif
|
||||
|
||||
#define TM16XX_CMD_DATA_AUTO 0x40
|
||||
#define TM16XX_CMD_DATA_READ 0x42 // command to read data used on two wire interfaces of TM1637
|
||||
#define TM16XX_CMD_DATA_FIXED 0x44
|
||||
#define TM16XX_CMD_DISPLAY 0x80
|
||||
#define TM16XX_CMD_ADDRESS 0xC0
|
||||
|
||||
// Common display modes for selecting different GRID x SEGMENT configuration
|
||||
// Used by e.g. TM1618, TM1620, TM1628, TM1630, TM1668
|
||||
// (note: TM1652 combined display control and uses a single bit to designate 5x8 or 6x8)
|
||||
#define TM16XX_CMD_MODE_4GRID 0x00
|
||||
#define TM16XX_CMD_MODE_5GRID 0x01 // TM1630: 4x8 - 5x7
|
||||
#define TM16XX_CMD_MODE_6GRID 0x02 // TM1620: 4x10 - 6x8
|
||||
#define TM16XX_CMD_MODE_7GRID 0x03 // TM1628, TM1668: 4x13 - 7x10, TM1624: 4x14 - 7x11, TM1618: 4x8 - 7x5
|
||||
|
||||
#include "TM16xxFonts.h"
|
||||
#include <driver/gpio.h>
|
||||
|
||||
class TM16xx
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Instantiate a TM16xx module specifying data, clock and strobe pins (no strobe on some modules),
|
||||
* the maximum number of displays supported by the chip (as provided by derived chip specific class),
|
||||
* the number of digits used to display numbers or text,
|
||||
* display state and the starting intensity (0-7).
|
||||
*/
|
||||
TM16xx(gpio_num_t dataPin, gpio_num_t clockPin, gpio_num_t strobePin, uint8_t maxDisplays, uint8_t nDigitsUsed, bool activateDisplay=true, uint8_t intensity=7);
|
||||
|
||||
/** Set the display (segments and LEDs) active or off and intensity (range from 0-7). */
|
||||
virtual void setupDisplay(bool active, uint8_t intensity);
|
||||
|
||||
/** Clear the display */
|
||||
virtual void clearDisplay();
|
||||
|
||||
/** Set segments of the display */
|
||||
virtual void setSegments(uint8_t segments, uint8_t position);
|
||||
virtual void setSegments16(uint16_t segments, uint8_t position); // some modules support more than 8 segments
|
||||
|
||||
// Basic display functions. For additional display features use the TM16xxDisplay class
|
||||
/** Set a single display at pos (starting at 0) to a digit (left to right) */
|
||||
virtual void setDisplayDigit(uint8_t digit, uint8_t pos=0, bool dot=false, const uint8_t numberFont[] = TM16XX_NUMBER_FONT);
|
||||
/** Set the display to a decimal number */
|
||||
virtual void setDisplayToDecNumber(int nNumber, uint8_t bDots=0);
|
||||
/** Clear a single display at pos (starting at 0, left to right) */
|
||||
virtual void clearDisplayDigit(uint8_t pos, bool dot=false);
|
||||
/** Set the display to the values (left to right) */
|
||||
virtual void setDisplay(const uint8_t values[], uint8_t size=8);
|
||||
|
||||
/** Set the display to the string (defaults to built in font) */
|
||||
virtual void setDisplayToString(const char* string, const uint32_t dots=0, const uint8_t pos=0, const uint8_t font[] = TM16XX_FONT_DEFAULT);
|
||||
virtual void sendChar(uint8_t pos, uint8_t data, bool dot); // made public to allow calling from TM16xxDisplay
|
||||
virtual uint8_t getNumDigits(); // added as public menthod to allow calling from TM16xxDisplay
|
||||
virtual void sendAsciiChar(uint8_t pos, char c, bool dot); // made public to allow calling from TM16xxDisplay
|
||||
|
||||
// Key-scanning functions
|
||||
// Note: not all TM16xx chips support key-scanning and sizes are different per chip
|
||||
// Up to 32 key states are supported, but specific chips may support less keys or less combinations
|
||||
// The chip specific derived class method will return a 32-bit value representing the state of each key, containing 0 if no key is pressed
|
||||
virtual uint32_t getButtons(); // return state of up to 32 keys.
|
||||
|
||||
protected:
|
||||
// virtual void sendChar(byte pos, byte data, bool dot);
|
||||
virtual void bitDelay();
|
||||
virtual void start();
|
||||
virtual void stop();
|
||||
virtual void send(uint8_t data);
|
||||
virtual void sendCommand(uint8_t led);
|
||||
virtual void sendData(uint8_t add, uint8_t data);
|
||||
virtual uint8_t receive();
|
||||
|
||||
#if !defined(max)
|
||||
// MMOLE 211229: use c++ function templates to implement our own min/max, as redefining them wont work in newer ESP cores when using certain wifi libraries
|
||||
// NOTE: min, max are no macro in ESP core 2.3.9 libraries, see https://github.com/esp8266/Arduino/issues/398
|
||||
// See also
|
||||
// https://www.cplusplus.com/doc/oldtutorial/templates/
|
||||
// https://www.alltestanswers.com/c-templates-for-the-two-functions-minimum-and-maximum/
|
||||
// https://www.learncpp.com/cpp-tutorial/function-templates-with-multiple-template-types/
|
||||
// MMOLE 220814: Arduino IDE 1.8.12 for LGT328P required "#if !defined(max)" to prevent compilation errors
|
||||
template <typename T, typename U>
|
||||
auto max(T x, U y) -> decltype(x>y ? x : y)
|
||||
{
|
||||
return x>y ? x : y;
|
||||
}
|
||||
template <typename T, typename U>
|
||||
auto min(T x, U y) -> decltype(x>y ? x : y)
|
||||
{
|
||||
return x<y ? x : y;
|
||||
}
|
||||
#endif // !defined(max)
|
||||
|
||||
uint8_t _maxDisplays=2; // maximum number of digits (grids), chip-dependent
|
||||
uint8_t _maxSegments=8; // maximum number of segments per display, chip-dependent
|
||||
|
||||
uint8_t digits; // number of digits in the display, module dependent
|
||||
gpio_num_t dataPin;
|
||||
gpio_num_t clockPin;
|
||||
gpio_num_t strobePin;
|
||||
};
|
||||
|
||||
#endif
|
||||
313
main/drivers/TM1640/TM16xxFonts.h
Normal file
313
main/drivers/TM1640/TM16xxFonts.h
Normal file
@ -0,0 +1,313 @@
|
||||
/*
|
||||
TM16xxFonts.h - Font definition for TM16xx.
|
||||
|
||||
Copyright (C) 2011 Ricardo Batista (rjbatista <at> gmail <dot> com)
|
||||
Modified by Maxint R&D. See https://github.com/maxint-rd/
|
||||
- Improvements for 7-segment alpha-numeric font
|
||||
- Additional 15-segment font
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the version 3 GNU General Public License as
|
||||
published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Segment labels
|
||||
-- A --
|
||||
| |
|
||||
F B
|
||||
-- G --
|
||||
E C
|
||||
| |
|
||||
-- D -- .DP
|
||||
|
||||
The bits are displayed by the mapping below:
|
||||
-- 0 --
|
||||
| |
|
||||
5 1
|
||||
-- 6 --
|
||||
4 2
|
||||
| |
|
||||
-- 3 -- .7
|
||||
|
||||
|
||||
Common pinout 7-segments x 4 digits:
|
||||
12 11 10 9 8 7
|
||||
| | | | | |
|
||||
+------------------------+ 12, 9, 8, 6: GRD1-GRD4
|
||||
| -- -- -- -- |
|
||||
| | | | | | | | | | 1: SEG_E 5: SEG_G
|
||||
| -- -- -- -- | 2: SEG_D 7: SEG_B
|
||||
| | | | | | | | | | 3: SEG_DP 10: SEG_F
|
||||
| -- . -- . -- . -- . | 4: SEG_C 11: SEG_A
|
||||
+------------------------+
|
||||
| | | | | |
|
||||
1 2 3 4 5 6
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TM16XXFonts_h
|
||||
#define TM16XXFonts_h
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// definition for standard hexadecimal numbers
|
||||
const uint8_t TM16XX_NUMBER_FONT[] = {
|
||||
0b00111111, // 0
|
||||
0b00000110, // 1
|
||||
0b01011011, // 2
|
||||
0b01001111, // 3
|
||||
0b01100110, // 4
|
||||
0b01101101, // 5
|
||||
0b01111101, // 6
|
||||
0b00000111, // 7
|
||||
0b01111111, // 8
|
||||
0b01101111, // 9
|
||||
0b01110111, // A
|
||||
0b01111100, // B
|
||||
0b00111001, // C
|
||||
0b01011110, // D
|
||||
0b01111001, // E
|
||||
0b01110001 // F
|
||||
};
|
||||
|
||||
const uint8_t MINUS = 0b01000000;
|
||||
|
||||
// definition for error text
|
||||
const uint8_t TM16XX_ERROR_DATA[] = {
|
||||
0b01111001, // E
|
||||
0b01010000, // r
|
||||
0b01010000, // r
|
||||
0b01011100, // o
|
||||
0b01010000, // r
|
||||
0,
|
||||
0,
|
||||
0
|
||||
};
|
||||
|
||||
// Definition for the displayable ASCII chars
|
||||
// (note that non-alpha-numeric characters may display as a space or a simple dash)
|
||||
const uint8_t TM16XX_FONT_DEFAULT[] = {
|
||||
0b00000000, // (32) <space>
|
||||
0b10000110, // (33) !
|
||||
0b00100010, // (34) "
|
||||
0b01111110, // (35) #
|
||||
0b01101101, // (36) $
|
||||
0b00000000, // (37) %
|
||||
0b00000000, // (38) &
|
||||
0b00000010, // (39) '
|
||||
0b00110000, // (40) (
|
||||
0b00000110, // (41) )
|
||||
0b01100011, // (42) *
|
||||
0b00000000, // (43) +
|
||||
0b00000100, // (44) ,
|
||||
0b01000000, // (45) -
|
||||
0b10000000, // (46) .
|
||||
0b01010010, // (47) /
|
||||
0b00111111, // (48) 0
|
||||
0b00000110, // (49) 1
|
||||
0b01011011, // (50) 2
|
||||
0b01001111, // (51) 3
|
||||
0b01100110, // (52) 4
|
||||
0b01101101, // (53) 5
|
||||
0b01111101, // (54) 6
|
||||
0b00100111, // (55) 7
|
||||
0b01111111, // (56) 8
|
||||
0b01101111, // (57) 9
|
||||
0b00000000, // (58) :
|
||||
0b00000000, // (59) ;
|
||||
0b00000000, // (60) <
|
||||
0b01001000, // (61) =
|
||||
0b00000000, // (62) >
|
||||
0b01010011, // (63) ?
|
||||
0b01011111, // (64) @
|
||||
0b01110111, // (65) A
|
||||
0b01111111, // (66) B
|
||||
0b00111001, // (67) C
|
||||
0b00111111, // (68) D
|
||||
0b01111001, // (69) E
|
||||
0b01110001, // (70) F
|
||||
0b00111101, // (71) G
|
||||
0b01110110, // (72) H
|
||||
0b00000110, // (73) I
|
||||
0b00011110, // (74) J
|
||||
0b01101001, // (75) K
|
||||
0b00111000, // (76) L
|
||||
0b00010101, // (77) M
|
||||
0b00110111, // (78) N
|
||||
0b00111111, // (79) O
|
||||
0b01110011, // (80) P
|
||||
0b01100111, // (81) Q
|
||||
0b00110001, // (82) R
|
||||
0b01101101, // (83) S
|
||||
0b01111000, // (84) T
|
||||
0b00111110, // (85) U
|
||||
0b00101010, // (86) V
|
||||
0b00011101, // (87) W
|
||||
0b01110110, // (88) X
|
||||
0b01101110, // (89) Y
|
||||
0b01011011, // (90) Z
|
||||
0b00111001, // (91) [
|
||||
0b01100100, // (92) \ (this can't be the last char on a line, even in comment or it'll concat)
|
||||
0b00001111, // (93) ]
|
||||
0b00000000, // (94) ^
|
||||
0b00001000, // (95) _
|
||||
0b00100000, // (96) `
|
||||
0b01011111, // (97) a
|
||||
0b01111100, // (98) b
|
||||
0b01011000, // (99) c
|
||||
0b01011110, // (100) d
|
||||
0b01111011, // (101) e
|
||||
0b00110001, // (102) f
|
||||
0b01101111, // (103) g
|
||||
0b01110100, // (104) h
|
||||
0b00000100, // (105) i
|
||||
0b00001110, // (106) j
|
||||
0b01110101, // (107) k
|
||||
0b00110000, // (108) l
|
||||
0b01010101, // (109) m
|
||||
0b01010100, // (110) n
|
||||
0b01011100, // (111) o
|
||||
0b01110011, // (112) p
|
||||
0b01100111, // (113) q
|
||||
0b01010000, // (114) r
|
||||
0b01101101, // (115) s
|
||||
0b01111000, // (116) t
|
||||
0b00011100, // (117) u
|
||||
0b00101010, // (118) v
|
||||
0b00011101, // (119) w
|
||||
0b01110110, // (120) x
|
||||
0b01101110, // (121) y
|
||||
0b01000111, // (122) z
|
||||
0b01000110, // (123) {
|
||||
0b00000110, // (124) |
|
||||
0b01110000, // (125) }
|
||||
0b00000001, // (126) ~
|
||||
};
|
||||
|
||||
/*
|
||||
Definition for the displayable ASCII chars on a 15-segment display.
|
||||
|
||||
Segment labels and bit-assignment:
|
||||
|---A---| Bit Segment Bit Segment
|
||||
|\ | /| [0] A [ 8] G2
|
||||
F H J K B [1] B [ 9] H
|
||||
| \|/ | [2] C [10] J
|
||||
|-G1-G2-| [3] D [11] K
|
||||
| /|\ | [4] E [12] L
|
||||
E N M L C [5] F [13] M
|
||||
|/ | \| [6] G1 [14] N
|
||||
|---D---| DP [7] DP
|
||||
|
||||
14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
N M L K J H G2 DP G1 F E D C B A
|
||||
|
||||
Note: For compatibility bits 0-7 are in the same order as A-G on a 7-segment display.
|
||||
Most characters in the font below are based on their 7-seg counterparts to keep styling alike.
|
||||
*/
|
||||
const uint16_t TM16XX_FONT_15SEG[] = {
|
||||
0b00000000, // (32) <space>
|
||||
0b10010010000000, // (33) !
|
||||
0b00100010, // (34) "
|
||||
0b10010101110001, // (35) #
|
||||
0b10010101101101, // (36) $
|
||||
0b100100000100100, // (37) %
|
||||
0b1101001011001, // (38) &
|
||||
0b00000010, // (39) '
|
||||
0b00110000, // (40) (
|
||||
0b00000110, // (41) )
|
||||
0b111111101000000, // (42) *
|
||||
0b010010101000000, // (43) +
|
||||
0b100000000000000, // (44) ,
|
||||
0b01000000, // (45) -
|
||||
0b10000000, // (46) .
|
||||
0b0100100000000000, // (47) /
|
||||
0b00111111, // (48) 0
|
||||
0b00000110, // (49) 1
|
||||
0b101011011, // (50) 2
|
||||
0b101001111, // (51) 3
|
||||
0b101100110, // (52) 4
|
||||
0b101101101, // (53) 5
|
||||
0b101111101, // (54) 6
|
||||
0b00100111, // (55) 7
|
||||
0b101111111, // (56) 8
|
||||
0b101101111, // (57) 9
|
||||
0b10000000, // (58) :
|
||||
0b100000000000010, // (59) ;
|
||||
0b1100000000000, // (60) <
|
||||
0b101001000, // (61) =
|
||||
0b100001000000000, // (62) >
|
||||
0b10000110000011, // (63) ?
|
||||
0b100111011, // (64) @
|
||||
0b101110111, // (65) A
|
||||
0b10010100001111, // (66) B
|
||||
0b00111001, // (67) C
|
||||
0b10010000001111, // (68) D
|
||||
0b101111001, // (69) E
|
||||
0b101110001, // (70) F
|
||||
0b100111101, // (71) G
|
||||
0b101110110, // (72) H
|
||||
0b10010000001001, // (73) I
|
||||
0b00011110, // (74) J
|
||||
0b01100001110000, // (75) K
|
||||
0b00111000, // (76) L
|
||||
0b101000110110, // (77) M
|
||||
0b1001000110110, // (78) N
|
||||
0b00111111, // (79) O
|
||||
0b101110011, // (80) P
|
||||
0b1000000111111, // (81) Q
|
||||
0b1000101110011, // (82) R
|
||||
0b101101101, // (83) S
|
||||
0b010010000000001, // (84) T
|
||||
0b00111110, // (85) U
|
||||
0b1001000000110, // (86) V
|
||||
0b101000000110110, // (87) W
|
||||
0b101101000000000, // (88) X
|
||||
0b00010101000000000, // (89) Y
|
||||
0b100100000001001, // (90) Z
|
||||
0b00111001, // (91) [
|
||||
0b1001000000000, // (92) \ (this can't be the last char on a line, even in comment or it'll concat)
|
||||
0b00001111, // (93) ]
|
||||
0b101000000000000, // (94) ^
|
||||
0b00001000, // (95) _
|
||||
0b1000000000, // (96) `
|
||||
0b101011111, // (97) a
|
||||
0b101111100, // (98) b
|
||||
0b101011000, // (99) c
|
||||
0b101011110, // (100) d
|
||||
0b101111011, // (101) e
|
||||
0b01110001, // (102) f
|
||||
0b101101111, // (103) g
|
||||
0b101110100, // (104) h
|
||||
0b00000100, // (105) i
|
||||
0b00001110, // (106) j
|
||||
0b100001110100, // (107) k
|
||||
0b00110000, // (108) l
|
||||
0b101000110110, // (109) m
|
||||
0b10000100000100, // (110) n
|
||||
0b101011100, // (111) o
|
||||
0b101110011, // (112) p
|
||||
0b101100111, // (113) q
|
||||
0b101010000, // (114) r
|
||||
0b101101101, // (115) s
|
||||
0b01111000, // (116) t
|
||||
0b00011100, // (117) u
|
||||
0b100000000010000, // (118) v
|
||||
0b101000000010100, // (119) w
|
||||
0b101101000000000, // (120) x
|
||||
0b100101000000000, // (121) y
|
||||
0b100100000001001, // (122) z
|
||||
0b100001001001001, // (123) {
|
||||
0b010010000000000, // (124) |
|
||||
0b1100100001001, // (125) }
|
||||
0b00000001, // (126) ~
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
93
main/drivers/sd.hpp
Normal file
93
main/drivers/sd.hpp
Normal file
@ -0,0 +1,93 @@
|
||||
#ifndef SD_HPP
|
||||
#define SD_HPP
|
||||
|
||||
#include <string.h>
|
||||
#include <sys/unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include "esp_vfs_fat.h"
|
||||
#include "sdmmc_cmd.h"
|
||||
#include "driver/sdmmc_host.h"
|
||||
|
||||
static const char *SD_TAG = "sd_driver";
|
||||
|
||||
#define MOUNT_POINT "/sdcard"
|
||||
|
||||
const char mount_point[] = MOUNT_POINT;
|
||||
sdmmc_card_t *card;
|
||||
|
||||
#define SD_PIN_CLK GPIO_NUM_48
|
||||
#define SD_PIN_CMD GPIO_NUM_45
|
||||
#define SD_PIN_D0 GPIO_NUM_47
|
||||
#define SD_PIN_D1 GPIO_NUM_21
|
||||
#define SD_PIN_D2 GPIO_NUM_39
|
||||
#define SD_PIN_D3 GPIO_NUM_38
|
||||
|
||||
void init_sd() {
|
||||
esp_err_t ret;
|
||||
|
||||
// Options for mounting the filesystem.
|
||||
// If format_if_mount_failed is set to true, SD card will be partitioned and
|
||||
// formatted in case when mounting fails.
|
||||
esp_vfs_fat_sdmmc_mount_config_t mount_config = {
|
||||
.format_if_mount_failed = false,
|
||||
.max_files = 5,
|
||||
.allocation_unit_size = 16 * 1024,
|
||||
.disk_status_check_enable = false,
|
||||
};
|
||||
|
||||
ESP_LOGI(SD_TAG, "Initializing SD card");
|
||||
|
||||
// Use settings defined above to initialize SD card and mount FAT filesystem.
|
||||
// Note: esp_vfs_fat_sdmmc/sdspi_mount is all-in-one convenience functions.
|
||||
// Please check its source code and implement error recovery when developing
|
||||
// production applications.
|
||||
|
||||
ESP_LOGI(SD_TAG, "Using SDMMC peripheral");
|
||||
sdmmc_host_t host = SDMMC_HOST_DEFAULT();
|
||||
|
||||
// This initializes the slot without card detect (CD) and write protect (WP) signals.
|
||||
// Modify slot_config.gpio_cd and slot_config.gpio_wp if your board has these signals.
|
||||
sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
|
||||
|
||||
// Set bus width to use:
|
||||
slot_config.width = 4;
|
||||
|
||||
// On chips where the GPIOs used for SD card can be configured, set them in
|
||||
// the slot_config structure:
|
||||
slot_config.clk = SD_PIN_CLK;
|
||||
slot_config.cmd = SD_PIN_CMD;
|
||||
slot_config.d0 = SD_PIN_D0;
|
||||
slot_config.d1 = SD_PIN_D1;
|
||||
slot_config.d2 = SD_PIN_D2;
|
||||
slot_config.d3 = SD_PIN_D3;
|
||||
|
||||
// Enable internal pullups on enabled pins. The internal pullups
|
||||
// are insufficient however, please make sure 10k external pullups are
|
||||
// connected on the bus. This is for debug / example purpose only.
|
||||
slot_config.flags |= SDMMC_SLOT_FLAG_INTERNAL_PULLUP;
|
||||
|
||||
ESP_LOGI(SD_TAG, "Mounting filesystem");
|
||||
ret = esp_vfs_fat_sdmmc_mount(mount_point, &host, &slot_config, &mount_config, &card);
|
||||
|
||||
if (ret != ESP_OK) {
|
||||
if (ret == ESP_FAIL) {
|
||||
ESP_LOGE(SD_TAG, "Failed to mount filesystem. "
|
||||
"If you want the card to be formatted, set the EXAMPLE_FORMAT_IF_MOUNT_FAILED menuconfig option.");
|
||||
} else {
|
||||
ESP_LOGE(SD_TAG, "Failed to initialize the card (%s). "
|
||||
"Make sure SD card lines have pull-up resistors in place.", esp_err_to_name(ret));
|
||||
}
|
||||
return;
|
||||
}
|
||||
ESP_LOGI(SD_TAG, "Filesystem mounted");
|
||||
|
||||
// Card has been initialized, print its properties
|
||||
sdmmc_card_print_info(stdout, card);
|
||||
}
|
||||
|
||||
void deinit_sd() {
|
||||
esp_vfs_fat_sdcard_unmount(mount_point, card);
|
||||
ESP_LOGI(SD_TAG, "Card unmounted");
|
||||
}
|
||||
|
||||
#endif /* SD_HPP */
|
||||
96
main/drivers/speaker.hpp
Normal file
96
main/drivers/speaker.hpp
Normal file
@ -0,0 +1,96 @@
|
||||
#ifndef SPEAKER_HPP
|
||||
#define SPEAKER_HPP
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "driver/i2s_std.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_check.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "sd.hpp"
|
||||
|
||||
#define SPEAKER_PIN_BCLK GPIO_NUM_46
|
||||
#define SPEAKER_PIN_WS GPIO_NUM_9
|
||||
#define SPEAKER_PIN_DOUT GPIO_NUM_3
|
||||
#define SAMPLE_RATE 44100
|
||||
#define AUDIO_BUFFER 2048
|
||||
|
||||
static i2s_chan_handle_t tx_chan;
|
||||
|
||||
static const char *SPEAKER_TAG = "speaker_driver";
|
||||
|
||||
esp_err_t play_raw(const char *fp) {
|
||||
FILE *fh = fopen(fp, "rb");
|
||||
if (fh == NULL)
|
||||
{
|
||||
ESP_LOGE(SPEAKER_TAG, "Failed to open file");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
// create a writer buffer
|
||||
uint8_t *read_buf = (uint8_t*) calloc(AUDIO_BUFFER, sizeof(uint8_t));
|
||||
uint16_t *write_buf = (uint16_t*) calloc(AUDIO_BUFFER, sizeof(uint16_t));
|
||||
size_t bytes_read = 0;
|
||||
size_t bytes_written = 0;
|
||||
|
||||
ESP_ERROR_CHECK(i2s_channel_enable(tx_chan));
|
||||
|
||||
bytes_read = fread(read_buf, sizeof(uint8_t), AUDIO_BUFFER, fh);
|
||||
for (int i = 0; i < bytes_read; i++) {
|
||||
write_buf[i] = read_buf[i];
|
||||
}
|
||||
|
||||
// i2s_channel_enable(tx_handle);
|
||||
|
||||
while (bytes_read > 0) {
|
||||
// write the buffer to the i2s
|
||||
// ESP_LOGI(TAG, "Writing: ");
|
||||
// for (int i = 0; i < words_read; i++) {
|
||||
// int16_t val = buf[i];
|
||||
// printf("%s0x%04X ", (val < 0 ? "-" : "+"), (val < 0 ? -val : val));
|
||||
// }>
|
||||
i2s_channel_write(tx_chan, write_buf, bytes_read * sizeof(int16_t), &bytes_written, portMAX_DELAY);
|
||||
bytes_read = fread(read_buf, sizeof(uint8_t), AUDIO_BUFFER, fh);
|
||||
for (int i = 0; i < bytes_read; i++) {
|
||||
write_buf[i] = read_buf[i] << 3;
|
||||
}
|
||||
ESP_LOGV(SPEAKER_TAG, "Bytes read: %d", bytes_read);
|
||||
}
|
||||
|
||||
i2s_channel_disable(tx_chan);
|
||||
free(read_buf);
|
||||
free(write_buf);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void init_speaker(void) {
|
||||
i2s_chan_config_t tx_chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_AUTO, I2S_ROLE_MASTER);
|
||||
ESP_ERROR_CHECK(i2s_new_channel(&tx_chan_cfg, &tx_chan, NULL));
|
||||
|
||||
i2s_std_config_t tx_std_cfg = {
|
||||
.clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(SAMPLE_RATE),
|
||||
.slot_cfg = I2S_STD_MSB_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_MONO),
|
||||
.gpio_cfg = {
|
||||
.mclk = I2S_GPIO_UNUSED,
|
||||
.bclk = SPEAKER_PIN_BCLK,
|
||||
.ws = SPEAKER_PIN_WS,
|
||||
.dout = SPEAKER_PIN_DOUT,
|
||||
.din = GPIO_NUM_NC,
|
||||
.invert_flags = {
|
||||
.mclk_inv = false,
|
||||
.bclk_inv = false,
|
||||
.ws_inv = false,
|
||||
},
|
||||
},
|
||||
};
|
||||
ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_chan, &tx_std_cfg));
|
||||
}
|
||||
|
||||
void play_example() {
|
||||
ESP_ERROR_CHECK_WITHOUT_ABORT(play_raw("/sdcard/o.pcm"));
|
||||
}
|
||||
|
||||
#endif /* SPEAKER_HPP */
|
||||
40
main/drivers/sseg.hpp
Normal file
40
main/drivers/sseg.hpp
Normal file
@ -0,0 +1,40 @@
|
||||
#ifndef SSEG_HPP
|
||||
#define SSEG_HPP
|
||||
|
||||
#include "TM1640/TM1640.h"
|
||||
#include <esp_log.h>
|
||||
|
||||
#define SSEG_PIN_DATA GPIO_NUM_10
|
||||
#define SSEG_PIN_CLK GPIO_NUM_11
|
||||
|
||||
static const char *SSEG_TAG = "sseg_driver";
|
||||
|
||||
TM1640* sseg = nullptr;
|
||||
|
||||
void init_sseg() {
|
||||
sseg = new TM1640(SSEG_PIN_DATA, SSEG_PIN_CLK, 8);
|
||||
}
|
||||
|
||||
void set_game_timer(unsigned int value, int dot_pos) {
|
||||
if (sseg == nullptr) {
|
||||
ESP_LOGE(SSEG_TAG, "SSEG display not initialized");
|
||||
}
|
||||
for (int i = 0; i < 4; i++) {
|
||||
auto idx = value % 10;
|
||||
sseg->sendChar(3-i, TM16XX_NUMBER_FONT[idx], i == dot_pos);
|
||||
value = value / 10;
|
||||
}
|
||||
}
|
||||
|
||||
void set_module_timer(unsigned int value, int dot_pos) {
|
||||
if (sseg == nullptr) {
|
||||
ESP_LOGE(SSEG_TAG, "SSEG display not initialized");
|
||||
}
|
||||
for (int i = 0; i < 4; i++) {
|
||||
auto idx = value % 10;
|
||||
sseg->sendChar(7-i, TM16XX_NUMBER_FONT[idx], i == dot_pos);
|
||||
value = value / 10;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* SSEG_HPP */
|
||||
282
main/drivers/tft.hpp
Normal file
282
main/drivers/tft.hpp
Normal file
@ -0,0 +1,282 @@
|
||||
#ifndef TFT_HPP
|
||||
#define TFT_HPP
|
||||
|
||||
/*
|
||||
* Adapted from an example under the MIT license:
|
||||
* Copyright © 2022 atanisoft (github.com/atanisoft)
|
||||
*
|
||||
* MIT LICENSE:
|
||||
* 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 <driver/gpio.h>
|
||||
#include <driver/ledc.h>
|
||||
#include <driver/spi_master.h>
|
||||
#include <esp_err.h>
|
||||
#include <esp_freertos_hooks.h>
|
||||
#include <esp_log.h>
|
||||
#include <esp_lcd_panel_io.h>
|
||||
#include <esp_lcd_panel_vendor.h>
|
||||
#include <esp_lcd_panel_ops.h>
|
||||
#include <esp_lcd_ili9488.h>
|
||||
#include <esp_timer.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
#include <lvgl.h>
|
||||
#include <stdio.h>
|
||||
#include "sdkconfig.h"
|
||||
|
||||
// Uncomment the following line to enable using double buffering of LVGL color
|
||||
// data.
|
||||
// #define USE_DOUBLE_BUFFERING 1
|
||||
|
||||
static const char *TFT_TAG = "tft_driver";
|
||||
|
||||
#define DISPLAY_HORIZONTAL_PIXELS 320
|
||||
#define DISPLAY_VERTICAL_PIXELS 480
|
||||
#define DISPLAY_COMMAND_BITS 8
|
||||
#define DISPLAY_PARAMETER_BITS 8
|
||||
#define DISPLAY_REFRESH_HZ 40000000
|
||||
#define DISPLAY_SPI_QUEUE_LEN 10
|
||||
#define SPI_MAX_TRANSFER_SIZE 32768
|
||||
|
||||
#define TFT_PIN_MOSI GPIO_NUM_17
|
||||
#define TFT_PIN_MISO GPIO_NUM_18
|
||||
#define TFT_PIN_CLK GPIO_NUM_16
|
||||
#define TFT_PIN_CS GPIO_NUM_NC
|
||||
#define TFT_PIN_DC GPIO_NUM_15
|
||||
#define TFT_PIN_RESET GPIO_NUM_8
|
||||
|
||||
#define TFT_INVERT_COLOR false
|
||||
|
||||
// Default to 50 lines of color data
|
||||
#define LV_BUFFER_SIZE DISPLAY_HORIZONTAL_PIXELS * 50
|
||||
#define LVGL_UPDATE_PERIOD_MS 5
|
||||
|
||||
#define BACKLIGHT_LEDC_MODE LEDC_LOW_SPEED_MODE
|
||||
#define BACKLIGHT_LEDC_CHANNEL LEDC_CHANNEL_0
|
||||
#define BACKLIGHT_LEDC_TIMER LEDC_TIMER_1
|
||||
#define BACKLIGHT_LEDC_TIMER_RESOLUTION LEDC_TIMER_10_BIT
|
||||
#define BACKLIGHT_LEDC_FRQUENCY 5000
|
||||
|
||||
static esp_lcd_panel_io_handle_t lcd_io_handle = NULL;
|
||||
static esp_lcd_panel_handle_t lcd_handle = NULL;
|
||||
|
||||
static lv_disp_draw_buf_t lv_disp_buf;
|
||||
static lv_disp_drv_t lv_disp_drv;
|
||||
static lv_disp_t *lv_display = NULL;
|
||||
static lv_color_t *lv_buf_1 = NULL;
|
||||
static lv_color_t *lv_buf_2 = NULL;
|
||||
static lv_obj_t *meter = NULL;
|
||||
static lv_style_t style_screen;
|
||||
|
||||
static void update_meter_value(void *indic, int32_t v)
|
||||
{
|
||||
lv_meter_set_indicator_end_value(meter, (lv_meter_indicator_t*)indic, v);
|
||||
}
|
||||
|
||||
static bool notify_lvgl_flush_ready(
|
||||
esp_lcd_panel_io_handle_t panel_io,
|
||||
esp_lcd_panel_io_event_data_t *edata,
|
||||
void *user_ctx
|
||||
) {
|
||||
lv_disp_drv_t *disp_driver = (lv_disp_drv_t *)user_ctx;
|
||||
lv_disp_flush_ready(disp_driver);
|
||||
return false;
|
||||
}
|
||||
|
||||
static void lvgl_flush_cb(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map) {
|
||||
esp_lcd_panel_handle_t panel_handle = (esp_lcd_panel_handle_t) drv->user_data;
|
||||
|
||||
int offsetx1 = area->x1;
|
||||
int offsetx2 = area->x2;
|
||||
int offsety1 = area->y1;
|
||||
int offsety2 = area->y2;
|
||||
esp_lcd_panel_draw_bitmap(panel_handle, offsetx1, offsety1, offsetx2 + 1, offsety2 + 1, color_map);
|
||||
}
|
||||
|
||||
static void IRAM_ATTR lvgl_tick_cb(void *param) {
|
||||
lv_tick_inc(LVGL_UPDATE_PERIOD_MS);
|
||||
}
|
||||
|
||||
void initialize_spi() {
|
||||
ESP_LOGI(TFT_TAG, "Initializing SPI bus (MOSI:%d, MISO:%d, CLK:%d)",
|
||||
TFT_PIN_MOSI, TFT_PIN_MISO, TFT_PIN_CLK);
|
||||
|
||||
spi_bus_config_t bus = {
|
||||
.mosi_io_num = TFT_PIN_MOSI,
|
||||
.miso_io_num = TFT_PIN_MISO,
|
||||
.sclk_io_num = TFT_PIN_CLK,
|
||||
.quadwp_io_num = GPIO_NUM_NC,
|
||||
.quadhd_io_num = GPIO_NUM_NC,
|
||||
.data4_io_num = GPIO_NUM_NC,
|
||||
.data5_io_num = GPIO_NUM_NC,
|
||||
.data6_io_num = GPIO_NUM_NC,
|
||||
.data7_io_num = GPIO_NUM_NC,
|
||||
.max_transfer_sz = SPI_MAX_TRANSFER_SIZE,
|
||||
.flags = SPICOMMON_BUSFLAG_SCLK | SPICOMMON_BUSFLAG_MISO |
|
||||
SPICOMMON_BUSFLAG_MOSI | SPICOMMON_BUSFLAG_MASTER,
|
||||
.isr_cpu_id = ESP_INTR_CPU_AFFINITY_AUTO,
|
||||
.intr_flags = ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_IRAM
|
||||
};
|
||||
|
||||
ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, &bus, SPI_DMA_CH_AUTO));
|
||||
}
|
||||
|
||||
void initialize_display() {
|
||||
const esp_lcd_panel_io_spi_config_t io_config = {
|
||||
.cs_gpio_num = TFT_PIN_CS,
|
||||
.dc_gpio_num = TFT_PIN_DC,
|
||||
.spi_mode = 0,
|
||||
.pclk_hz = DISPLAY_REFRESH_HZ,
|
||||
.trans_queue_depth = DISPLAY_SPI_QUEUE_LEN,
|
||||
.on_color_trans_done = notify_lvgl_flush_ready,
|
||||
.user_ctx = &lv_disp_drv,
|
||||
.lcd_cmd_bits = DISPLAY_COMMAND_BITS,
|
||||
.lcd_param_bits = DISPLAY_PARAMETER_BITS,
|
||||
.flags = {
|
||||
.dc_high_on_cmd = 0, /*!< If enabled, DC level = 1 indicates command transfer */
|
||||
.dc_low_on_data = 0, /*!< If enabled, DC level = 0 indicates color data transfer */
|
||||
.dc_low_on_param = 0, /*!< If enabled, DC level = 0 indicates parameter transfer */
|
||||
.octal_mode = 0, /*!< transmit with octal mode (8 data lines), this mode is used to simulate Intel 8080 timing */
|
||||
.quad_mode = 0, /*!< transmit with quad mode (4 data lines), this mode is useful when transmitting LCD parameters (Only use one line for command) */
|
||||
.sio_mode = 0, /*!< Read and write through a single data line (MOSI) */
|
||||
.lsb_first = 0, /*!< transmit LSB bit first */
|
||||
.cs_high_active = 0, /*!< CS line is high active */
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const esp_lcd_panel_dev_config_t lcd_config = {
|
||||
.reset_gpio_num = TFT_PIN_RESET,
|
||||
.color_space = LCD_RGB_ELEMENT_ORDER_BGR,
|
||||
.data_endian = LCD_RGB_DATA_ENDIAN_BIG,
|
||||
.bits_per_pixel = 18,
|
||||
.flags = {
|
||||
.reset_active_high = 0
|
||||
},
|
||||
.vendor_config = NULL
|
||||
};
|
||||
|
||||
ESP_ERROR_CHECK(
|
||||
esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)SPI2_HOST, &io_config, &lcd_io_handle));
|
||||
|
||||
ESP_ERROR_CHECK(esp_lcd_new_panel_ili9488(lcd_io_handle, &lcd_config, LV_BUFFER_SIZE, &lcd_handle));
|
||||
|
||||
ESP_ERROR_CHECK(esp_lcd_panel_reset(lcd_handle));
|
||||
ESP_ERROR_CHECK(esp_lcd_panel_init(lcd_handle));
|
||||
ESP_ERROR_CHECK(esp_lcd_panel_invert_color(lcd_handle, false));
|
||||
ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(lcd_handle, false));
|
||||
ESP_ERROR_CHECK(esp_lcd_panel_mirror(lcd_handle, true, false));
|
||||
ESP_ERROR_CHECK(esp_lcd_panel_set_gap(lcd_handle, 0, 0));
|
||||
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||
ESP_ERROR_CHECK(esp_lcd_panel_disp_off(lcd_handle, false));
|
||||
#else
|
||||
ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(lcd_handle, true));
|
||||
#endif
|
||||
}
|
||||
|
||||
void initialize_lvgl() {
|
||||
ESP_LOGI(TFT_TAG, "Initializing LVGL");
|
||||
lv_init();
|
||||
ESP_LOGI(TFT_TAG, "Allocating %zu bytes for LVGL buffer", LV_BUFFER_SIZE * sizeof(lv_color_t));
|
||||
lv_buf_1 = (lv_color_t *)heap_caps_malloc(LV_BUFFER_SIZE * sizeof(lv_color_t), MALLOC_CAP_DMA);
|
||||
#if USE_DOUBLE_BUFFERING
|
||||
ESP_LOGI(TFT_TAG, "Allocating %zu bytes for second LVGL buffer", LV_BUFFER_SIZE * sizeof(lv_color_t));
|
||||
lv_buf_2 = (lv_color_t *)heap_caps_malloc(LV_BUFFER_SIZE * sizeof(lv_color_t), MALLOC_CAP_DMA);
|
||||
#endif
|
||||
ESP_LOGI(TFT_TAG, "Creating LVLG display buffer");
|
||||
lv_disp_draw_buf_init(&lv_disp_buf, lv_buf_1, lv_buf_2, LV_BUFFER_SIZE);
|
||||
|
||||
ESP_LOGI(TFT_TAG, "Initializing %dx%d display", DISPLAY_HORIZONTAL_PIXELS, DISPLAY_VERTICAL_PIXELS);
|
||||
lv_disp_drv_init(&lv_disp_drv);
|
||||
lv_disp_drv.hor_res = DISPLAY_HORIZONTAL_PIXELS;
|
||||
lv_disp_drv.ver_res = DISPLAY_VERTICAL_PIXELS;
|
||||
lv_disp_drv.flush_cb = lvgl_flush_cb;
|
||||
lv_disp_drv.draw_buf = &lv_disp_buf;
|
||||
lv_disp_drv.user_data = lcd_handle;
|
||||
lv_display = lv_disp_drv_register(&lv_disp_drv);
|
||||
|
||||
ESP_LOGI(TFT_TAG, "Creating LVGL tick timer");
|
||||
const esp_timer_create_args_t lvgl_tick_timer_args = {
|
||||
.callback = &lvgl_tick_cb,
|
||||
.arg = NULL,
|
||||
.dispatch_method = ESP_TIMER_TASK,
|
||||
.name = "lvgl_tick",
|
||||
.skip_unhandled_events = false
|
||||
};
|
||||
esp_timer_handle_t lvgl_tick_timer = NULL;
|
||||
ESP_ERROR_CHECK(esp_timer_create(&lvgl_tick_timer_args, &lvgl_tick_timer));
|
||||
ESP_ERROR_CHECK(esp_timer_start_periodic(lvgl_tick_timer, LVGL_UPDATE_PERIOD_MS * 1000));
|
||||
}
|
||||
|
||||
void create_demo_ui() {
|
||||
lv_obj_t *scr = lv_disp_get_scr_act(NULL);
|
||||
|
||||
// Set the background color of the display to black.
|
||||
lv_style_init(&style_screen);
|
||||
lv_style_set_bg_color(&style_screen, lv_color_black());
|
||||
lv_obj_add_style(lv_scr_act(), &style_screen, LV_STATE_DEFAULT);
|
||||
|
||||
// Create a meter which can be animated.
|
||||
meter = lv_meter_create(scr);
|
||||
lv_obj_center(meter);
|
||||
lv_obj_set_size(meter, 200, 200);
|
||||
|
||||
// Add a scale first
|
||||
lv_meter_scale_t *scale = lv_meter_add_scale(meter);
|
||||
lv_meter_set_scale_ticks(meter, scale, 41, 2, 10, lv_palette_main(LV_PALETTE_GREY));
|
||||
lv_meter_set_scale_major_ticks(meter, scale, 8, 4, 15, lv_color_black(), 10);
|
||||
|
||||
lv_meter_indicator_t *indic;
|
||||
|
||||
// Add a blue arc to the start
|
||||
indic = lv_meter_add_arc(meter, scale, 3, lv_palette_main(LV_PALETTE_BLUE), 0);
|
||||
lv_meter_set_indicator_start_value(meter, indic, 0);
|
||||
lv_meter_set_indicator_end_value(meter, indic, 20);
|
||||
|
||||
// Make the tick lines blue at the start of the scale
|
||||
indic = lv_meter_add_scale_lines(meter, scale, lv_palette_main(LV_PALETTE_BLUE), lv_palette_main(LV_PALETTE_BLUE), false, 0);
|
||||
lv_meter_set_indicator_start_value(meter, indic, 0);
|
||||
lv_meter_set_indicator_end_value(meter, indic, 20);
|
||||
|
||||
// Add a red arc to the end
|
||||
indic = lv_meter_add_arc(meter, scale, 3, lv_palette_main(LV_PALETTE_RED), 0);
|
||||
lv_meter_set_indicator_start_value(meter, indic, 80);
|
||||
lv_meter_set_indicator_end_value(meter, indic, 100);
|
||||
|
||||
// Make the tick lines red at the end of the scale
|
||||
indic = lv_meter_add_scale_lines(meter, scale, lv_palette_main(LV_PALETTE_RED), lv_palette_main(LV_PALETTE_RED), false, 0);
|
||||
lv_meter_set_indicator_start_value(meter, indic, 80);
|
||||
lv_meter_set_indicator_end_value(meter, indic, 100);
|
||||
|
||||
// Add a needle line indicator
|
||||
indic = lv_meter_add_needle_line(meter, scale, 4, lv_palette_main(LV_PALETTE_GREY), -10);
|
||||
|
||||
// Create an animation to set the value
|
||||
lv_anim_t a;
|
||||
lv_anim_init(&a);
|
||||
lv_anim_set_exec_cb(&a, update_meter_value);
|
||||
lv_anim_set_var(&a, indic);
|
||||
lv_anim_set_values(&a, 0, 100);
|
||||
lv_anim_set_time(&a, 2000);
|
||||
lv_anim_set_repeat_delay(&a, 100);
|
||||
lv_anim_set_playback_time(&a, 500);
|
||||
lv_anim_set_playback_delay(&a, 100);
|
||||
lv_anim_set_repeat_count(&a, LV_ANIM_REPEAT_INFINITE);
|
||||
lv_anim_start(&a);
|
||||
}
|
||||
|
||||
void init_tft() {
|
||||
initialize_spi();
|
||||
initialize_display();
|
||||
initialize_lvgl();
|
||||
|
||||
ESP_LOGI(TFT_TAG, "TFT initialization Successful");
|
||||
}
|
||||
|
||||
#endif /* TFT_HPP */
|
||||
18
main/idf_component.yml
Normal file
18
main/idf_component.yml
Normal file
@ -0,0 +1,18 @@
|
||||
## IDF Component Manager Manifest File
|
||||
dependencies:
|
||||
lvgl/lvgl: "^8.1"
|
||||
atanisoft/esp_lcd_ili9488: "^1.0.9"
|
||||
## Required IDF version
|
||||
idf:
|
||||
version: ">=4.1.0"
|
||||
# # Put list of dependencies here
|
||||
# # For components maintained by Espressif:
|
||||
# component: "~1.0.0"
|
||||
# # For 3rd party components:
|
||||
# username/component: ">=1.0.0,<2.0.0"
|
||||
# username2/component2:
|
||||
# version: "~1.0.0"
|
||||
# # For transient dependencies `public` flag can be set.
|
||||
# # `public` flag doesn't have an effect dependencies of the `main` component.
|
||||
# # All dependencies of `main` are public by default.
|
||||
# public: true
|
||||
151
main/main.cpp
Executable file
151
main/main.cpp
Executable file
@ -0,0 +1,151 @@
|
||||
#include <stdio.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "driver/uart.h"
|
||||
#include "driver/i2c.h"
|
||||
#include "drivers/tft.hpp"
|
||||
#include "drivers/sd.hpp"
|
||||
#include "drivers/sseg.hpp"
|
||||
#include "drivers/speaker.hpp"
|
||||
#include "esp_rom_gpio.h"
|
||||
|
||||
#define WIRES_ADDR 125
|
||||
#define WIRES_REG_WIRES
|
||||
|
||||
|
||||
static const char *TAG = "main";
|
||||
static void relay_task(void *arg);
|
||||
|
||||
extern "C" void app_main(void) {
|
||||
printf("app_main\n");
|
||||
|
||||
// init_sd();
|
||||
|
||||
// init_tft();
|
||||
// create_demo_ui();
|
||||
|
||||
// init_speaker();
|
||||
// play_example();
|
||||
|
||||
// deinit_sd();
|
||||
|
||||
init_sseg();
|
||||
set_game_timer(1234, 1);
|
||||
set_module_timer(5678, 2);
|
||||
|
||||
// while (1) {
|
||||
// vTaskDelay(pdMS_TO_TICKS(10));
|
||||
// lv_timer_handler();
|
||||
// }
|
||||
|
||||
// UART relay
|
||||
xTaskCreate(relay_task, "relay_task", 4096, NULL, 10, NULL);
|
||||
|
||||
i2c_config_t conf = {
|
||||
.mode = I2C_MODE_MASTER,
|
||||
.sda_io_num = GPIO_NUM_5,
|
||||
.scl_io_num = GPIO_NUM_6,
|
||||
.sda_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.scl_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.master = {
|
||||
.clk_speed = 100000,
|
||||
}
|
||||
};
|
||||
|
||||
ESP_ERROR_CHECK(i2c_param_config(I2C_NUM_0, &conf));
|
||||
ESP_ERROR_CHECK(i2c_driver_install(I2C_NUM_0, conf.mode, 0, 0, 0));
|
||||
|
||||
gpio_reset_pin(GPIO_NUM_41);
|
||||
gpio_reset_pin(GPIO_NUM_42);
|
||||
|
||||
i2c_config_t wires_conf = {
|
||||
.mode = I2C_MODE_MASTER,
|
||||
.sda_io_num = GPIO_NUM_41,
|
||||
.scl_io_num = GPIO_NUM_42,
|
||||
.sda_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.scl_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.master = {
|
||||
.clk_speed = 100000,
|
||||
}
|
||||
};
|
||||
|
||||
ESP_ERROR_CHECK(i2c_param_config(I2C_NUM_1, &wires_conf));
|
||||
ESP_ERROR_CHECK(i2c_driver_install(I2C_NUM_1, wires_conf.mode, 0, 0, 0));
|
||||
|
||||
|
||||
// uint8_t write[8] = {1, 2, 4, 8, 16, 32, 64, 128};
|
||||
|
||||
while (1) {
|
||||
vTaskDelay(pdMS_TO_TICKS(5000));
|
||||
uint8_t read[8] = {0};
|
||||
uint8_t reg;
|
||||
|
||||
// reg = 1;
|
||||
// ESP_ERROR_CHECK_WITHOUT_ABORT(i2c_master_write_read_device(I2C_NUM_0, 126, ®, 1, read, 1, (100 / portTICK_PERIOD_MS)));
|
||||
// ESP_LOGI("main", "delta: %d", read[0]);
|
||||
|
||||
// read[0] = 0;
|
||||
// reg = 2;
|
||||
// ESP_ERROR_CHECK_WITHOUT_ABORT(i2c_master_write_read_device(I2C_NUM_0, 126, ®, 1, read, 2, (100 / portTICK_PERIOD_MS)));
|
||||
// ESP_LOGI("main", "keypad: %d %d", read[0], read[1]);
|
||||
|
||||
|
||||
// WIRES
|
||||
reg = 1;
|
||||
ESP_ERROR_CHECK_WITHOUT_ABORT(i2c_master_write_read_device(I2C_NUM_1, 125, ®, 1, read, 1, (1000 / portTICK_PERIOD_MS)));
|
||||
ESP_LOGI("main", "wires: %d", read[0]);
|
||||
|
||||
// Issue strike
|
||||
reg = 5;
|
||||
ESP_ERROR_CHECK_WITHOUT_ABORT(i2c_master_write_to_device(I2C_NUM_1, 125, ®, 1, (1000 / portTICK_PERIOD_MS)));
|
||||
ESP_LOGI("main", "Strike!");
|
||||
|
||||
// vTaskDelay(pdMS_TO_TICKS(10));
|
||||
vTaskDelay(pdMS_TO_TICKS(20000));
|
||||
// vTaskDelay(pdMS_TO_TICKS(5000));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define BUF_SIZE (1024)
|
||||
#define TX_PIN GPIO_NUM_
|
||||
|
||||
static void relay_task(void *arg)
|
||||
{
|
||||
/* Configure parameters of an UART driver,
|
||||
* communication pins and install the driver */
|
||||
uart_config_t uart_config = {
|
||||
.baud_rate = 115200,
|
||||
.data_bits = UART_DATA_8_BITS,
|
||||
.parity = UART_PARITY_DISABLE,
|
||||
.stop_bits = UART_STOP_BITS_1,
|
||||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
||||
.source_clk = UART_SCLK_DEFAULT,
|
||||
};
|
||||
int intr_alloc_flags = 0;
|
||||
|
||||
#if CONFIG_UART_ISR_IN_IRAM
|
||||
intr_alloc_flags = ESP_INTR_FLAG_IRAM;
|
||||
#endif
|
||||
|
||||
ESP_ERROR_CHECK(uart_driver_install(UART_NUM_0, BUF_SIZE * 2, 0, 0, NULL, intr_alloc_flags));
|
||||
ESP_ERROR_CHECK(uart_param_config(UART_NUM_0, &uart_config));
|
||||
ESP_ERROR_CHECK(uart_set_pin(UART_NUM_0, GPIO_NUM_1, GPIO_NUM_2, GPIO_NUM_NC, GPIO_NUM_NC));
|
||||
|
||||
// Configure a temporary buffer for the incoming data
|
||||
uint8_t *data = (uint8_t *) malloc(BUF_SIZE);
|
||||
|
||||
while (1) {
|
||||
// Read data from the UART
|
||||
int len = uart_read_bytes(UART_NUM_0, data, (BUF_SIZE - 1), 20 / portTICK_PERIOD_MS);
|
||||
// Write data back to the UART
|
||||
// uart_write_bytes(ECHO_UART_PORT_NUM, (const char *) data, len);
|
||||
if (len) {
|
||||
data[len] = '\0';
|
||||
// ESP_LOGI(TAG, "%s", (char *) data);
|
||||
printf("%s", (char *) data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user