Skip to content

[ISSUE-24]: TM1637 driver and example #25

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 25, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,14 @@ THis list is supposed to grow longer and longer.
* Low level peripheral access (via registers).
* Peripheral controller drivers
* I2C
* RMT (TODO: example on RX)
* RMT
* _TODO_ SPI
* _TODO_ etc.
* Device drivers
* BME280 Temperature / Pressure / Humidity sensor
* (_TODO_: cleanup) BH1750 Light sensor
* DHT22 Temperature / Humidity sensor
* TM1637 4x7 segment display
* WS2812B LED strip
* etc (_TODO_)

Expand Down Expand Up @@ -119,6 +121,6 @@ Feel free to fork this project and play around with it integrating your own sens

## About license

The memory arrangement (see esp32.ld) and start-up code (main.c) is based on [esp32-minimal](https://github.com/aykevl/esp32-minimal).
This project also contains code (see xtutils.h) directly taken from the official [ESP32 SDK](https://github.com/espressif/esp-idf),
The memory arrangement (see [esp32.ld](ld/esp32.ld)) and start-up code ([main.c](src/main.c)) is based on [esp32-minimal](https://github.com/aykevl/esp32-minimal).
This project also contains code (see [xtutils.h](src/xtutils.h)) directly taken from the official [ESP32 SDK](https://github.com/espressif/esp-idf),
which is released under Apache-2.0.
2 changes: 2 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ AC_CONFIG_SUBDIRS([examples/1rmtblink])
AC_CONFIG_SUBDIRS([examples/1rmtdht])
AC_CONFIG_SUBDIRS([examples/1rmtmorse])
AC_CONFIG_SUBDIRS([examples/1rmtmusic])
AC_CONFIG_SUBDIRS([examples/1rmttm1637])
AC_CONFIG_SUBDIRS([examples/1rmtws2812])
AC_CONFIG_SUBDIRS([examples/3prog1])
AC_CONFIG_SUBDIRS([ld])
Expand All @@ -39,6 +40,7 @@ AC_CONFIG_FILES([
examples/1rmtdht/Makefile
examples/1rmtmorse/Makefile
examples/1rmtmusic/Makefile
examples/1rmttm1637/Makefile
examples/1rmtws2812/Makefile
examples/3prog1/Makefile
ld/Makefile
Expand Down
6 changes: 3 additions & 3 deletions examples/1rmtdht/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ The 1-wire protocol is implemented in `modules/dht22.c`.
#### Connections

```
ESP32.GPIO2 -- S1.OUT
ESP32.GND -- S1.-
ESP32.VCC -- S1.+
ESP32.GPIO21 -- S1.OUT
ESP32.GND -- S1.-
ESP32.VCC -- S1.+
```

#### Practices
Expand Down
37 changes: 37 additions & 0 deletions examples/1rmttm1637/Makefile.am
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
include $(top_srcdir)/scripts/elf2bin.mk
include $(top_srcdir)/ld/flags.mk

noinst_HEADERS = defines.h

AM_CFLAGS = -std=c11 -flto

if WITH_BINARIES
AM_LDFLAGS += \
-T $(top_srcdir)/ld/esp32.rom.ld \
-T $(top_srcdir)/ld/esp32.rom.libgcc.ld \
-T $(top_srcdir)/ld/esp32.rom.newlib-data.ld \
-T $(top_srcdir)/ld/esp32.rom.newlib-locale.ld \
-T $(top_srcdir)/ld/esp32.rom.newlib-nano.ld \
-T $(top_srcdir)/ld/esp32.rom.newlib-time.ld \
-T $(top_srcdir)/ld/esp32.rom.redefined.ld \
-T $(top_srcdir)/ld/esp32.rom.syscalls.ld
else
AM_LDFLAGS += \
-T $(top_srcdir)/ld/esp32.rom.ld \
-T $(top_srcdir)/ld/esp32.rom.libgcc.ld \
-T $(top_srcdir)/ld/esp32.rom.redefined.ld \
-T $(top_srcdir)/ld/esp32.rom.syscalls.ld
endif

AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/modules
LDADD = $(top_builddir)/src/libesp32basic.a $(top_builddir)/modules/libesp32modules.a

bin_PROGRAMS = \
rmttm1637.elf

if WITH_BINARIES
CLEANFILES = \
rmttm1637.bin
endif

BUILT_SOURCES = $(CLEANFILES)
24 changes: 24 additions & 0 deletions examples/1rmttm1637/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
### TM1637 display example

In this example the TM1637 displays hexadecimal numbers form `0` to `F`.
Each digit displays the same number.
The colon between the 2nd and the 3rd digits is blinking every second.
Each number is displayed for 3 seconds:
1 second full brightness, 1 second medium brightness and 1 second low brightness.


#### Hardware components

* X1: TM1637 display

#### Connections

```
ESP32.GPIO21 -- X1.CLK
ESP32.GPIO19 -- X1.DIO
ESP32.GND -- X1.GND
ESP32.VCC -- X1.VCC
```

#### Practices

39 changes: 39 additions & 0 deletions examples/1rmttm1637/defines.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright 2024 SZIGETI János
*
* This file is part of Bilis ESP32 Basic, which is released under GNU General Public License.version 3.
* See LICENSE or <https://www.gnu.org/licenses/> for full license details.
*/
#ifndef DEFINES_H
#define DEFINES_H

#ifdef __cplusplus
extern "C" {
#endif

// TIMINGS
// const -- do not change this value
#define APB_FREQ_HZ 80000000U // 80 MHz

// variables
#define TIM0_0_DIVISOR 2U
#define START_APP_CPU 0U
#define SCHEDULE_FREQ_HZ 1000U // 1KHz

// derived invariants
#define CLK_FREQ_HZ (APB_FREQ_HZ / TIM0_0_DIVISOR) // 40 MHz
#define TICKS_PER_MS (CLK_FREQ_HZ / 1000U) // 40000
#define TICKS_PER_US (CLK_FREQ_HZ / 1000000U) // 40
#define NS_PER_TICKS (1000000000 / CLK_FREQ_HZ)

#define TICKS2NS(X) ((X) * NS_PER_TICKS)
#define TICKS2US(X) ((X) / TICKS_PER_US)
#define MS2TICKS(X) ((X) * TICKS_PER_MS)
#define HZ2APBTICKS(X) (APB_FREQ_HZ / (X))

#ifdef __cplusplus
}
#endif

#endif /* DEFINES_H */

133 changes: 133 additions & 0 deletions examples/1rmttm1637/rmttm1637.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/*
* Copyright 2024 SZIGETI János
*
* This file is part of Bilis ESP32 Basic, which is released under GNU General Public License.version 3.
* See LICENSE or <https://www.gnu.org/licenses/> for full license details.
*/
#include <stdbool.h>
#include <inttypes.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>

#include "tm1637.h"
#include "gpio.h"
#include "main.h"
#include "rmt.h"
#include "defines.h"
#include "romfunctions.h"
#include "iomux.h"
#include "dport.h"
#include "timg.h"
#include "typeaux.h"
#include "utils/uartutils.h"

// =================== Hard constants =================
// #1: Timings
#define RMTTM1637_PERIOD_MS 500U

// #2: Channels / wires / addresses
#define CLK_GPIO 21U
#define DIO_GPIO 19U
#define CLK_CH RMT_CH1
#define DIO_CH RMT_CH0

#define RMTINT_CH 23U

// ============= Local types ===============
typedef struct {
STm1637State *psState;
uint64_t u64tckStart;
} SReadyCbParam;

// ================ Local function declarations =================
static void _rmttm1637_ready(void *pvParam);
static void _rmttm1637_init();
static void _rmttm1637_cycle(uint64_t u64Ticks);

// =================== Global constants ================
const bool gbStartAppCpu = START_APP_CPU;
const uint16_t gu16Tim00Divisor = TIM0_0_DIVISOR;
const uint64_t gu64tckSchedulePeriod = (CLK_FREQ_HZ / SCHEDULE_FREQ_HZ);

// ==================== Local Data ================
static const TimerId gsTimer = {.eTimg = TIMG_0, .eTimer = TIMER0};
const uint8_t gau8NumToSeg[] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71};

static STm1637State gsTm1637State;
static SReadyCbParam gsReadyData;

// ==================== Implementation ================

static void _rmttm1637_ready(void *pvParam) {
SReadyCbParam *psParam = (SReadyCbParam*) pvParam;
uint64_t u64TckStop = timg_ticks(gsTimer);
uart_printf(&gsUART0, "Display ready (failed ACKs: %08X)\tDt: %d ns\n",
psParam->psState->u32Internals,
TICKS2NS((uint32_t) (u64TckStop - psParam->u64tckStart)));
}

static void _rmttm1637_init() {
rmt_isr_init();
rmt_init_controller(true, true);
STm1637Iface sIface = { CLK_GPIO, DIO_GPIO, CLK_CH, DIO_CH};
gsTm1637State = tm1637_config(&sIface);
tm1637_init(&gsTm1637State, APB_FREQ_HZ);
tm1637_set_readycb(&gsTm1637State, _rmttm1637_ready, &gsReadyData);
gsReadyData.psState = &gsTm1637State;
rmt_isr_start(CPU_PRO, RMTINT_CH);
}

static void _rmttm1637_cycle(uint64_t u64Ticks) {
static uint64_t u64NextTick = MS2TICKS(RMTTM1637_PERIOD_MS);
static uint8_t au8Data[4];
static uint8_t u8DatIdx = 0; // What number to display (put into au8Data)? Cycling through gau8NumToSeg: [0..15]
static uint8_t u8Phase = 0; // Display phase: last bit is 0: display dot (8th segment of the digits), bits 1, 2: brightness level

if (u64NextTick <= u64Ticks) {
// local, derived variables
bool bDot = (0 == (u8Phase & 1));
uint8_t u8Brightness = 7 - (3 * (u8Phase / 2)); // three levels: 7, 4, 1

uart_printf(&gsUART0, "Cycle %u %u\t", u8DatIdx, u8Phase);
tm1637_set_brightness(&gsTm1637State, true, u8Brightness);
for (int i = 0; i < 4; ++i) {
au8Data[i] = gau8NumToSeg[u8DatIdx] | (bDot ? 0x80 : 0x00);
}
tm1637_set_data(&gsTm1637State, au8Data);
gsReadyData.u64tckStart = timg_ticks(gsTimer);
tm1637_display(&gsTm1637State);

// jump to next state
++u8Phase;
if (6 == u8Phase) {
u8Phase = 0;
++u8DatIdx;
if (u8DatIdx == ARRAY_SIZE(gau8NumToSeg)) {
u8DatIdx = 0;
}
}
u64NextTick += MS2TICKS(RMTTM1637_PERIOD_MS);
}
}

// ====================== Interface functions =========================

void prog_init_pro_pre() {
gsUART0.CLKDIV = APB_FREQ_HZ / 115200;

_rmttm1637_init();
}

void prog_init_app() {
}

void prog_init_pro_post() {
}

void prog_cycle_app(uint64_t u64tckNow) {
}

void prog_cycle_pro(uint64_t u64tckNow) {
_rmttm1637_cycle(u64tckNow);
}
2 changes: 1 addition & 1 deletion examples/Makefile.am
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
AUTOMAKE_OPTIONS =
SUBDIRS=0blink 0button 0hello 0ledctrl 1rmtblink 1rmtdht 1rmtmorse 1rmtmusic 3prog1 1rmtws2812
SUBDIRS=0blink 0button 0hello 0ledctrl 1rmtblink 1rmtdht 1rmtmorse 1rmtmusic 1rmttm1637 3prog1 1rmtws2812
4 changes: 2 additions & 2 deletions modules/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ libesp32modules_a_AR=$(AR) rcs

lib_LIBRARIES = libesp32modules.a

include_HEADERS = bh1750.h bme280.h dht22.h ws2812.h
include_HEADERS = bh1750.h bme280.h dht22.h tm1637.h ws2812.h
nodist_include_HEADERS =

libesp32modules_a_SOURCES = bh1750.c bme280.c dht22.c ws2812.c
libesp32modules_a_SOURCES = bh1750.c bme280.c dht22.c tm1637.c ws2812.c
nodist_libesp32modules_a_SOURCES =

CLEANFILES =
Expand Down
Loading
Loading