Initial working rotating nametag
This commit is contained in:
commit
07a0f30d72
|
@ -0,0 +1,5 @@
|
|||
.pio
|
||||
.vscode/.browse.c_cpp.db*
|
||||
.vscode/c_cpp_properties.json
|
||||
.vscode/launch.json
|
||||
.vscode/ipch
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
// See http://go.microsoft.com/fwlink/?LinkId=827846
|
||||
// for the documentation about the extensions.json format
|
||||
"recommendations": [
|
||||
"platformio.platformio-ide"
|
||||
],
|
||||
"unwantedRecommendations": [
|
||||
"ms-vscode.cpptools-extension-pack"
|
||||
]
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
|
||||
This directory is intended for project header files.
|
||||
|
||||
A header file is a file containing C declarations and macro definitions
|
||||
to be shared between several project source files. You request the use of a
|
||||
header file in your project source file (C, C++, etc) located in `src` folder
|
||||
by including it, with the C preprocessing directive `#include'.
|
||||
|
||||
```src/main.c
|
||||
|
||||
#include "header.h"
|
||||
|
||||
int main (void)
|
||||
{
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
Including a header file produces the same results as copying the header file
|
||||
into each source file that needs it. Such copying would be time-consuming
|
||||
and error-prone. With a header file, the related declarations appear
|
||||
in only one place. If they need to be changed, they can be changed in one
|
||||
place, and programs that include the header file will automatically use the
|
||||
new version when next recompiled. The header file eliminates the labor of
|
||||
finding and changing all the copies as well as the risk that a failure to
|
||||
find one copy will result in inconsistencies within a program.
|
||||
|
||||
In C, the usual convention is to give header files names that end with `.h'.
|
||||
It is most portable to use only letters, digits, dashes, and underscores in
|
||||
header file names, and at most one dot.
|
||||
|
||||
Read more about using header files in official GCC documentation:
|
||||
|
||||
* Include Syntax
|
||||
* Include Operation
|
||||
* Once-Only Headers
|
||||
* Computed Includes
|
||||
|
||||
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
|
|
@ -0,0 +1,36 @@
|
|||
#ifndef __GC9A01_H
|
||||
#define __GC9A01_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Hardware abstraction layer
|
||||
// Should be defined by the user of the library
|
||||
void GC9A01_set_reset(uint8_t val);
|
||||
void GC9A01_set_data_command(uint8_t val);
|
||||
void GC9A01_set_chip_select(uint8_t val);
|
||||
void GC9A01_delay(uint16_t ms);
|
||||
void GC9A01_spi_tx(uint8_t *data, size_t len);
|
||||
|
||||
struct GC9A01_point {
|
||||
uint16_t X, Y;
|
||||
};
|
||||
|
||||
struct GC9A01_frame {
|
||||
struct GC9A01_point start, end;
|
||||
};
|
||||
|
||||
void GC9A01_init(void);
|
||||
void GC9A01_set_frame(struct GC9A01_frame frame);
|
||||
void GC9A01_write(uint8_t *data, size_t len);
|
||||
void GC9A01_write_continue(uint8_t *data, size_t len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,98 @@
|
|||
#ifndef _INC_HSV2RGB_H
|
||||
#define _INC_HSV2RGB_H
|
||||
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
typedef struct color_rgb {
|
||||
uint8_t r;
|
||||
uint8_t g;
|
||||
uint8_t b;
|
||||
} color_rgb;
|
||||
|
||||
typedef struct color_hsv {
|
||||
int16_t h;
|
||||
uint8_t s;
|
||||
uint8_t v;
|
||||
} color_hsv;
|
||||
|
||||
|
||||
#define HSV_HUE_SEXTANT 256
|
||||
#define HSV_HUE_STEPS (6 * HSV_HUE_SEXTANT)
|
||||
|
||||
#define HSV_HUE_MIN 0
|
||||
#define HSV_HUE_MAX (HSV_HUE_STEPS - 1)
|
||||
#define HSV_SAT_MIN 0
|
||||
#define HSV_SAT_MAX 255
|
||||
#define HSV_VAL_MIN 0
|
||||
#define HSV_VAL_MAX 255
|
||||
|
||||
/* Options: */
|
||||
#define HSV_USE_SEXTANT_TEST /* Limit the hue to 0...360 degrees */
|
||||
|
||||
|
||||
void hsv2rgb_8b(int16_t h, uint8_t s, uint8_t v, uint8_t *r, uint8_t *g , uint8_t *b);
|
||||
|
||||
|
||||
/*
|
||||
* Macros that are common to all implementations
|
||||
*/
|
||||
#ifdef HSV_USE_SEXTANT_TEST
|
||||
#define HSV_SEXTANT_TEST(sextant) \
|
||||
if((sextant) > 5) { \
|
||||
(sextant) = 5; \
|
||||
}
|
||||
|
||||
#else
|
||||
#define HSV_SEXTANT_TEST(sextant)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Pointer swapping:
|
||||
* sext. r g b r<>b g<>b r <> g result
|
||||
* 0 0 0 v u c !u v c u v c
|
||||
* 0 0 1 d v c d v c
|
||||
* 0 1 0 c v u u v c u v c
|
||||
* 0 1 1 c d v v d c d v c d v c
|
||||
* 1 0 0 u c v u v c u v c
|
||||
* 1 0 1 v c d v d c d v c d v c
|
||||
*
|
||||
* if(sextant & 2)
|
||||
* r <-> b
|
||||
*
|
||||
* if(sextant & 4)
|
||||
* g <-> b
|
||||
*
|
||||
* if(!(sextant & 6) {
|
||||
* if(!(sextant & 1))
|
||||
* r <-> g
|
||||
* } else {
|
||||
* if(sextant & 1)
|
||||
* r <-> g
|
||||
* }
|
||||
*/
|
||||
#define HSV_SWAPPTR(a,b) do { uint8_t *tmp = (a); (a) = (b); (b) = tmp; } while(0)
|
||||
#define HSV_POINTER_SWAP(sextant,r,g,b) \
|
||||
do { \
|
||||
if((sextant) & 2) { \
|
||||
HSV_SWAPPTR((r), (b)); \
|
||||
} \
|
||||
if((sextant) & 4) { \
|
||||
HSV_SWAPPTR((g), (b)); \
|
||||
} \
|
||||
if(!((sextant) & 6)) { \
|
||||
if(!((sextant) & 1)) { \
|
||||
HSV_SWAPPTR((r), (g)); \
|
||||
} \
|
||||
} else { \
|
||||
if((sextant) & 1) { \
|
||||
HSV_SWAPPTR((r), (g)); \
|
||||
} \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
|
||||
|
||||
#endif /* _INC_HSV2RGB_H */
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* Example for a interpolated sine/cosine table lookup
|
||||
*
|
||||
* @file sin1.h
|
||||
* @author stfwi
|
||||
*
|
||||
*/
|
||||
#ifndef __SW__SIN1_H__
|
||||
#define __SW__SIN1_H__
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
/**
|
||||
* Sine calculation using interpolated table lookup.
|
||||
* Instead of radiants or degrees we use "turns" here. Means this
|
||||
* sine does NOT return one phase for 0 to 2*PI, but for 0 to 1.
|
||||
* Input: -1 to 1 as int16 Q15 == -32768 to 32767.
|
||||
* Output: -1 to 1 as int16 Q15 == -32768 to 32767.
|
||||
*
|
||||
* @param int16_t angle Q15
|
||||
* @return int16_t Q15
|
||||
*/
|
||||
int16_t sin1(int16_t angle);
|
||||
|
||||
/**
|
||||
* Cosine calculation using interpolated table lookup.
|
||||
* Instead of radiants or degrees we use "turns" here. Means this
|
||||
* cosine does NOT return one phase for 0 to 2*PI, but for 0 to 1.
|
||||
* Input: -1 to 1 as int16 Q15 == -32768 to 32767.
|
||||
* Output: -1 to 1 as int16 Q15 == -32768 to 32767.
|
||||
*
|
||||
* @param int16_t angle Q15
|
||||
* @return int16_t Q15
|
||||
*/
|
||||
int16_t cos1(int16_t angle);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* Example for a interpolated sine/cosine table lookup
|
||||
*
|
||||
* modified by true to work in 8 bits, and to fix cos7 function
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef INC_MATH_SIN7_H_
|
||||
#define INC_MATH_SIN7_H_
|
||||
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Sine calculation using interpolated table lookup.
|
||||
* Instead of radians or degrees we use "turns" here. Means this
|
||||
* sine does NOT return one phase for 0 to 2*PI, but for 0 to 1.
|
||||
* Input: -1 to 1 as int8 "Q7" == -128 to 127.
|
||||
* Output: -1 to 1 as int8 "Q7" == -128 to 127.
|
||||
*
|
||||
* @param int8_t angle Q7
|
||||
* @return int8_t Q7
|
||||
*/
|
||||
int8_t sin7(int8_t angle);
|
||||
|
||||
/**
|
||||
* Cosine calculation using interpolated table lookup.
|
||||
* Instead of radians or degrees we use "turns" here. Means this
|
||||
* cosine does NOT return one phase for 0 to 2*PI, but for 0 to 1.
|
||||
* Input: -1 to 1 as int8 "Q7" == -128 to 127.
|
||||
* Output: -1 to 1 as int8 "Q7" == -128 to 127.
|
||||
*
|
||||
* @param int8_t angle Q7
|
||||
* @return int8_t Q7
|
||||
*/
|
||||
int8_t cos7(int8_t angle);
|
||||
|
||||
|
||||
|
||||
#endif /* INC_MATH_SIN7_H_ */
|
|
@ -0,0 +1,46 @@
|
|||
|
||||
This directory is intended for project specific (private) libraries.
|
||||
PlatformIO will compile them to static libraries and link into executable file.
|
||||
|
||||
The source code of each library should be placed in a an own separate directory
|
||||
("lib/your_library_name/[here are source files]").
|
||||
|
||||
For example, see a structure of the following two libraries `Foo` and `Bar`:
|
||||
|
||||
|--lib
|
||||
| |
|
||||
| |--Bar
|
||||
| | |--docs
|
||||
| | |--examples
|
||||
| | |--src
|
||||
| | |- Bar.c
|
||||
| | |- Bar.h
|
||||
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
|
||||
| |
|
||||
| |--Foo
|
||||
| | |- Foo.c
|
||||
| | |- Foo.h
|
||||
| |
|
||||
| |- README --> THIS FILE
|
||||
|
|
||||
|- platformio.ini
|
||||
|--src
|
||||
|- main.c
|
||||
|
||||
and a contents of `src/main.c`:
|
||||
```
|
||||
#include <Foo.h>
|
||||
#include <Bar.h>
|
||||
|
||||
int main (void)
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
PlatformIO Library Dependency Finder will find automatically dependent
|
||||
libraries scanning project source files.
|
||||
|
||||
More information about PlatformIO Library Dependency Finder
|
||||
- https://docs.platformio.org/page/librarymanager/ldf.html
|
|
@ -0,0 +1,26 @@
|
|||
; PlatformIO Project Configuration File
|
||||
;
|
||||
; Build options: build flags, source filter
|
||||
; Upload options: custom upload port, speed and extra flags
|
||||
; Library options: dependencies, extra library storages
|
||||
; Advanced options: extra scripting
|
||||
;
|
||||
; Please visit documentation for the other options and examples
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[env:supercon7-badge-pico]
|
||||
platform = https://github.com/maxgerhardt/platform-raspberrypi.git
|
||||
board = rpipico
|
||||
framework = arduino
|
||||
|
||||
board_build.filesystem_size = 1m
|
||||
|
||||
debug_build_flags =
|
||||
-g
|
||||
-Os
|
||||
|
||||
lib_deps =
|
||||
moononournation/GFX Library for Arduino@^1.3.8
|
||||
|
||||
platform_packages =
|
||||
toolchain-gccarmnoneeabi@1.100301.220327
|
|
@ -0,0 +1,316 @@
|
|||
#include "GC9A01.h"
|
||||
|
||||
#define ORIENTATION 2 // Set the display orientation 0,1,2,3
|
||||
|
||||
// Command codes:
|
||||
#define COL_ADDR_SET 0x2A
|
||||
#define ROW_ADDR_SET 0x2B
|
||||
#define MEM_WR 0x2C
|
||||
#define COLOR_MODE 0x3A
|
||||
#define COLOR_MODE__12_BIT 0x03
|
||||
#define COLOR_MODE__16_BIT 0x05
|
||||
#define COLOR_MODE__18_BIT 0x06
|
||||
#define MEM_WR_CONT 0x3C
|
||||
|
||||
static void GC9A01_write_command(uint8_t cmd) {
|
||||
GC9A01_set_data_command(0);
|
||||
GC9A01_set_chip_select(0);
|
||||
GC9A01_spi_tx(&cmd, sizeof(cmd));
|
||||
GC9A01_set_chip_select(1);
|
||||
}
|
||||
|
||||
static void GC9A01_write_data(uint8_t *data, size_t len) {
|
||||
GC9A01_set_data_command(1);
|
||||
GC9A01_set_chip_select(0);
|
||||
GC9A01_spi_tx(data, len);
|
||||
GC9A01_set_chip_select(1);
|
||||
}
|
||||
|
||||
static inline void GC9A01_write_byte(uint8_t val) {
|
||||
GC9A01_write_data(&val, sizeof(val));
|
||||
}
|
||||
|
||||
void GC9A01_init(void) {
|
||||
|
||||
GC9A01_set_chip_select(1);
|
||||
GC9A01_delay(5);
|
||||
GC9A01_set_reset(0);
|
||||
GC9A01_delay(10);
|
||||
GC9A01_set_reset(1);
|
||||
GC9A01_delay(120);
|
||||
|
||||
/* Initial Sequence */
|
||||
|
||||
GC9A01_write_command(0xEF);
|
||||
|
||||
GC9A01_write_command(0xEB);
|
||||
GC9A01_write_byte(0x14);
|
||||
|
||||
GC9A01_write_command(0xFE);
|
||||
GC9A01_write_command(0xEF);
|
||||
|
||||
GC9A01_write_command(0xEB);
|
||||
GC9A01_write_byte(0x14);
|
||||
|
||||
GC9A01_write_command(0x84);
|
||||
GC9A01_write_byte(0x40);
|
||||
|
||||
GC9A01_write_command(0x85);
|
||||
GC9A01_write_byte(0xFF);
|
||||
|
||||
GC9A01_write_command(0x86);
|
||||
GC9A01_write_byte(0xFF);
|
||||
|
||||
GC9A01_write_command(0x87);
|
||||
GC9A01_write_byte(0xFF);
|
||||
|
||||
GC9A01_write_command(0x88);
|
||||
GC9A01_write_byte(0x0A);
|
||||
|
||||
GC9A01_write_command(0x89);
|
||||
GC9A01_write_byte(0x21);
|
||||
|
||||
GC9A01_write_command(0x8A);
|
||||
GC9A01_write_byte(0x00);
|
||||
|
||||
GC9A01_write_command(0x8B);
|
||||
GC9A01_write_byte(0x80);
|
||||
|
||||
GC9A01_write_command(0x8C);
|
||||
GC9A01_write_byte(0x01);
|
||||
|
||||
GC9A01_write_command(0x8D);
|
||||
GC9A01_write_byte(0x01);
|
||||
|
||||
GC9A01_write_command(0x8E);
|
||||
GC9A01_write_byte(0xFF);
|
||||
|
||||
GC9A01_write_command(0x8F);
|
||||
GC9A01_write_byte(0xFF);
|
||||
|
||||
|
||||
GC9A01_write_command(0xB6);
|
||||
GC9A01_write_byte(0x00);
|
||||
GC9A01_write_byte(0x00);
|
||||
|
||||
GC9A01_write_command(0x36);
|
||||
|
||||
#if ORIENTATION == 0
|
||||
GC9A01_write_byte(0x18);
|
||||
#elif ORIENTATION == 1
|
||||
GC9A01_write_byte(0x28);
|
||||
#elif ORIENTATION == 2
|
||||
GC9A01_write_byte(0x48);
|
||||
#else
|
||||
GC9A01_write_byte(0x88);
|
||||
#endif
|
||||
|
||||
GC9A01_write_command(COLOR_MODE);
|
||||
GC9A01_write_byte(COLOR_MODE__18_BIT);
|
||||
|
||||
GC9A01_write_command(0x90);
|
||||
GC9A01_write_byte(0x08);
|
||||
GC9A01_write_byte(0x08);
|
||||
GC9A01_write_byte(0x08);
|
||||
GC9A01_write_byte(0x08);
|
||||
|
||||
GC9A01_write_command(0xBD);
|
||||
GC9A01_write_byte(0x06);
|
||||
|
||||
GC9A01_write_command(0xBC);
|
||||
GC9A01_write_byte(0x00);
|
||||
|
||||
GC9A01_write_command(0xFF);
|
||||
GC9A01_write_byte(0x60);
|
||||
GC9A01_write_byte(0x01);
|
||||
GC9A01_write_byte(0x04);
|
||||
|
||||
GC9A01_write_command(0xC3);
|
||||
GC9A01_write_byte(0x13);
|
||||
GC9A01_write_command(0xC4);
|
||||
GC9A01_write_byte(0x13);
|
||||
|
||||
GC9A01_write_command(0xC9);
|
||||
GC9A01_write_byte(0x22);
|
||||
|
||||
GC9A01_write_command(0xBE);
|
||||
GC9A01_write_byte(0x11);
|
||||
|
||||
GC9A01_write_command(0xE1);
|
||||
GC9A01_write_byte(0x10);
|
||||
GC9A01_write_byte(0x0E);
|
||||
|
||||
GC9A01_write_command(0xDF);
|
||||
GC9A01_write_byte(0x21);
|
||||
GC9A01_write_byte(0x0c);
|
||||
GC9A01_write_byte(0x02);
|
||||
|
||||
GC9A01_write_command(0xF0);
|
||||
GC9A01_write_byte(0x45);
|
||||
GC9A01_write_byte(0x09);
|
||||
GC9A01_write_byte(0x08);
|
||||
GC9A01_write_byte(0x08);
|
||||
GC9A01_write_byte(0x26);
|
||||
GC9A01_write_byte(0x2A);
|
||||
|
||||
GC9A01_write_command(0xF1);
|
||||
GC9A01_write_byte(0x43);
|
||||
GC9A01_write_byte(0x70);
|
||||
GC9A01_write_byte(0x72);
|
||||
GC9A01_write_byte(0x36);
|
||||
GC9A01_write_byte(0x37);
|
||||
GC9A01_write_byte(0x6F);
|
||||
|
||||
GC9A01_write_command(0xF2);
|
||||
GC9A01_write_byte(0x45);
|
||||
GC9A01_write_byte(0x09);
|
||||
GC9A01_write_byte(0x08);
|
||||
GC9A01_write_byte(0x08);
|
||||
GC9A01_write_byte(0x26);
|
||||
GC9A01_write_byte(0x2A);
|
||||
|
||||
GC9A01_write_command(0xF3);
|
||||
GC9A01_write_byte(0x43);
|
||||
GC9A01_write_byte(0x70);
|
||||
GC9A01_write_byte(0x72);
|
||||
GC9A01_write_byte(0x36);
|
||||
GC9A01_write_byte(0x37);
|
||||
GC9A01_write_byte(0x6F);
|
||||
|
||||
GC9A01_write_command(0xED);
|
||||
GC9A01_write_byte(0x1B);
|
||||
GC9A01_write_byte(0x0B);
|
||||
|
||||
GC9A01_write_command(0xAE);
|
||||
GC9A01_write_byte(0x77);
|
||||
|
||||
GC9A01_write_command(0xCD);
|
||||
GC9A01_write_byte(0x63);
|
||||
|
||||
GC9A01_write_command(0x70);
|
||||
GC9A01_write_byte(0x07);
|
||||
GC9A01_write_byte(0x07);
|
||||
GC9A01_write_byte(0x04);
|
||||
GC9A01_write_byte(0x0E);
|
||||
GC9A01_write_byte(0x0F);
|
||||
GC9A01_write_byte(0x09);
|
||||
GC9A01_write_byte(0x07);
|
||||
GC9A01_write_byte(0x08);
|
||||
GC9A01_write_byte(0x03);
|
||||
|
||||
GC9A01_write_command(0xE8);
|
||||
GC9A01_write_byte(0x34);
|
||||
|
||||
GC9A01_write_command(0x62);
|
||||
GC9A01_write_byte(0x18);
|
||||
GC9A01_write_byte(0x0D);
|
||||
GC9A01_write_byte(0x71);
|
||||
GC9A01_write_byte(0xED);
|
||||
GC9A01_write_byte(0x70);
|
||||
GC9A01_write_byte(0x70);
|
||||
GC9A01_write_byte(0x18);
|
||||
GC9A01_write_byte(0x0F);
|
||||
GC9A01_write_byte(0x71);
|
||||
GC9A01_write_byte(0xEF);
|
||||
GC9A01_write_byte(0x70);
|
||||
GC9A01_write_byte(0x70);
|
||||
|
||||
GC9A01_write_command(0x63);
|
||||
GC9A01_write_byte(0x18);
|
||||
GC9A01_write_byte(0x11);
|
||||
GC9A01_write_byte(0x71);
|
||||
GC9A01_write_byte(0xF1);
|
||||
GC9A01_write_byte(0x70);
|
||||
GC9A01_write_byte(0x70);
|
||||
GC9A01_write_byte(0x18);
|
||||
GC9A01_write_byte(0x13);
|
||||
GC9A01_write_byte(0x71);
|
||||
GC9A01_write_byte(0xF3);
|
||||
GC9A01_write_byte(0x70);
|
||||
GC9A01_write_byte(0x70);
|
||||
|
||||
GC9A01_write_command(0x64);
|
||||
GC9A01_write_byte(0x28);
|
||||
GC9A01_write_byte(0x29);
|
||||
GC9A01_write_byte(0xF1);
|
||||
GC9A01_write_byte(0x01);
|
||||
GC9A01_write_byte(0xF1);
|
||||
GC9A01_write_byte(0x00);
|
||||
GC9A01_write_byte(0x07);
|
||||
|
||||
GC9A01_write_command(0x66);
|
||||
GC9A01_write_byte(0x3C);
|
||||
GC9A01_write_byte(0x00);
|
||||
GC9A01_write_byte(0xCD);
|
||||
GC9A01_write_byte(0x67);
|
||||
GC9A01_write_byte(0x45);
|
||||
GC9A01_write_byte(0x45);
|
||||
GC9A01_write_byte(0x10);
|
||||
GC9A01_write_byte(0x00);
|
||||
GC9A01_write_byte(0x00);
|
||||
GC9A01_write_byte(0x00);
|
||||
|
||||
GC9A01_write_command(0x67);
|
||||
GC9A01_write_byte(0x00);
|
||||
GC9A01_write_byte(0x3C);
|
||||
GC9A01_write_byte(0x00);
|
||||
GC9A01_write_byte(0x00);
|
||||
GC9A01_write_byte(0x00);
|
||||
GC9A01_write_byte(0x01);
|
||||
GC9A01_write_byte(0x54);
|
||||
GC9A01_write_byte(0x10);
|
||||
GC9A01_write_byte(0x32);
|
||||
GC9A01_write_byte(0x98);
|
||||
|
||||
GC9A01_write_command(0x74);
|
||||
GC9A01_write_byte(0x10);
|
||||
GC9A01_write_byte(0x85);
|
||||
GC9A01_write_byte(0x80);
|
||||
GC9A01_write_byte(0x00);
|
||||
GC9A01_write_byte(0x00);
|
||||
GC9A01_write_byte(0x4E);
|
||||
GC9A01_write_byte(0x00);
|
||||
|
||||
GC9A01_write_command(0x98);
|
||||
GC9A01_write_byte(0x3e);
|
||||
GC9A01_write_byte(0x07);
|
||||
|
||||
GC9A01_write_command(0x35);
|
||||
GC9A01_write_command(0x21);
|
||||
|
||||
GC9A01_write_command(0x11);
|
||||
GC9A01_delay(120);
|
||||
GC9A01_write_command(0x29);
|
||||
GC9A01_delay(20);
|
||||
|
||||
}
|
||||
|
||||
void GC9A01_set_frame(struct GC9A01_frame frame) {
|
||||
|
||||
uint8_t data[4];
|
||||
|
||||
GC9A01_write_command(COL_ADDR_SET);
|
||||
data[0] = (frame.start.X >> 8) & 0xFF;
|
||||
data[1] = frame.start.X & 0xFF;
|
||||
data[2] = (frame.end.X >> 8) & 0xFF;
|
||||
data[3] = frame.end.X & 0xFF;
|
||||
GC9A01_write_data(data, sizeof(data));
|
||||
|
||||
GC9A01_write_command(ROW_ADDR_SET);
|
||||
data[0] = (frame.start.Y >> 8) & 0xFF;
|
||||
data[1] = frame.start.Y & 0xFF;
|
||||
data[2] = (frame.end.Y >> 8) & 0xFF;
|
||||
data[3] = frame.end.Y & 0xFF;
|
||||
GC9A01_write_data(data, sizeof(data));
|
||||
|
||||
}
|
||||
|
||||
void GC9A01_write(uint8_t *data, size_t len) {
|
||||
GC9A01_write_command(MEM_WR);
|
||||
GC9A01_write_data(data, len);
|
||||
}
|
||||
|
||||
void GC9A01_write_continue(uint8_t *data, size_t len) {
|
||||
GC9A01_write_command(MEM_WR_CONT);
|
||||
GC9A01_write_data(data, len);
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 B. Stultiens
|
||||
*
|
||||
* 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 "hsv2rgb.h"
|
||||
|
||||
|
||||
void hsv2rgb_8b(int16_t h, uint8_t s, uint8_t v, uint8_t *r, uint8_t *g , uint8_t *b)
|
||||
{
|
||||
uint8_t sextant;
|
||||
uint8_t bb;
|
||||
uint16_t ww;
|
||||
uint8_t h_fraction;
|
||||
|
||||
if (!(s)) {
|
||||
*(r) = *(g) = *(b) = (v);
|
||||
return;
|
||||
}
|
||||
|
||||
sextant = h >> 8;
|
||||
HSV_SEXTANT_TEST(sextant); // Optional: Limit hue sextants to defined space
|
||||
|
||||
HSV_POINTER_SWAP(sextant, r, g, b); // Swap pointers depending which sextant we are in
|
||||
|
||||
*g = v; // Top level
|
||||
|
||||
// Perform actual calculations
|
||||
/*
|
||||
* Bottom level: v * (1.0 - s)
|
||||
* --> (v * (255 - s) + error_corr) / 256
|
||||
*/
|
||||
bb = ~s;
|
||||
ww = v * bb;
|
||||
ww += 1; // Error correction
|
||||
ww += ww >> 8; // Error correction
|
||||
*b = ww >> 8;
|
||||
|
||||
h_fraction = h & 0xff; // 0...255
|
||||
|
||||
if(!(sextant & 1)) {
|
||||
// *r = ...slope_up...;
|
||||
/*
|
||||
* Slope up: v * (1.0 - s * (1.0 - h))
|
||||
* --> (v * (255 - (s * (256 - h) + error_corr1) / 256) + error_corr2) / 256
|
||||
*/
|
||||
ww = !h_fraction ? ((uint16_t)s << 8) : (s * (uint8_t)(-h_fraction));
|
||||
ww += ww >> 8; // Error correction 1
|
||||
bb = ww >> 8;
|
||||
bb = ~bb;
|
||||
ww = v * bb;
|
||||
ww += v >> 1; // Error correction 2
|
||||
*r = ww >> 8;
|
||||
} else {
|
||||
// *r = ...slope_down...;
|
||||
/*
|
||||
* Slope down: v * (1.0 - s * h)
|
||||
* --> (v * (255 - (s * h + error_corr1) / 256) + error_corr2) / 256
|
||||
*/
|
||||
ww = s * h_fraction;
|
||||
ww += ww >> 8; // Error correction 1
|
||||
bb = ww >> 8;
|
||||
bb = ~bb;
|
||||
ww = v * bb;
|
||||
ww += v >> 1; // Error correction 2
|
||||
*r = ww >> 8;
|
||||
|
||||
/*
|
||||
* A perfect match for h_fraction == 0 implies:
|
||||
* *r = (ww >> 8) + (h_fraction ? 0 : 1)
|
||||
* However, this is an extra calculation that may not be required.
|
||||
*/
|
||||
}
|
||||
}
|
|
@ -0,0 +1,305 @@
|
|||
#include <Arduino.h>
|
||||
|
||||
#include "SPI.h"
|
||||
// #include "GC9A01.h"
|
||||
#include <Arduino_GFX_Library.h>
|
||||
#include <U8g2lib.h>
|
||||
|
||||
extern "C" {
|
||||
#include "hsv2rgb.h"
|
||||
#include "sin1.h"
|
||||
#include "sin7.h"
|
||||
}
|
||||
|
||||
|
||||
const char name[] = "true";
|
||||
|
||||
|
||||
|
||||
#define SPI0_SCK 2
|
||||
#define SPI0_MISO GFX_NOT_DEFINED
|
||||
#define SPI0_MOSI 3
|
||||
|
||||
#define DISP_NSS 1
|
||||
#define DISP_RESET 4
|
||||
#define DISP_DC 5
|
||||
|
||||
#define TEXT_SIZE 5
|
||||
#define ROT_SIZE 70
|
||||
|
||||
#define LETTER_SPACING 1898 // user-configurable
|
||||
|
||||
|
||||
Arduino_DataBus *bus = new Arduino_RPiPicoSPI(DISP_DC, DISP_NSS, SPI0_SCK, SPI0_MOSI, SPI0_MISO, spi0);
|
||||
Arduino_GFX *disp = new Arduino_GC9A01(bus, DISP_RESET, 0 /* rotation */, true /* IPS */);
|
||||
|
||||
Arduino_Canvas *dout = new Arduino_Canvas(240 /* width */, 240 /* height */, disp);
|
||||
Arduino_Canvas *drot = new Arduino_Canvas(ROT_SIZE, ROT_SIZE, disp);
|
||||
|
||||
|
||||
color_hsv hsv = {0, 255, 255};
|
||||
color_rgb rgb;
|
||||
|
||||
|
||||
/*
|
||||
void GC9A01_set_reset(uint8_t val) {
|
||||
digitalWrite(DISP_RESET, val);
|
||||
}
|
||||
|
||||
void GC9A01_set_data_command(uint8_t val) {
|
||||
digitalWrite(DISP_DC, val);
|
||||
}
|
||||
|
||||
void GC9A01_set_chip_select(uint8_t val) {
|
||||
digitalWrite(DISP_NSS, val);
|
||||
}
|
||||
|
||||
void GC9A01_spi_tx(uint8_t *data, size_t len) {
|
||||
while (len--) {
|
||||
SPI.transfer(*data);
|
||||
data++;
|
||||
}
|
||||
}
|
||||
|
||||
void GC9A01_delay(uint16_t ms) {
|
||||
delay(ms);
|
||||
}
|
||||
|
||||
void setup() {
|
||||
|
||||
pinMode(DISP_RESET, OUTPUT);
|
||||
pinMode(DISP_DC, OUTPUT);
|
||||
pinMode(DISP_NSS, OUTPUT);
|
||||
|
||||
SPI.setRX(SPI0_MISO);
|
||||
SPI.setSCK(SPI0_SCK);
|
||||
SPI.setTX(SPI0_MOSI);
|
||||
|
||||
SPI.begin();
|
||||
|
||||
GC9A01_init();
|
||||
struct GC9A01_frame frame = {{0,0},{239,239}};
|
||||
GC9A01_set_frame(frame);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
uint8_t color[3];
|
||||
|
||||
// Triangle
|
||||
color[0] = 0xFF;
|
||||
color[1] = 0xFF;
|
||||
for (int x = 0; x < 240; x++) {
|
||||
for (int y = 0; y < 240; y++) {
|
||||
if (x < y) {
|
||||
color[2] = 0xFF;
|
||||
} else {
|
||||
color[2] = 0x00;
|
||||
}
|
||||
if (x == 0 && y == 0) {
|
||||
GC9A01_write(color, sizeof(color));
|
||||
} else {
|
||||
GC9A01_write_continue(color, sizeof(color));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delay(1000);
|
||||
|
||||
// Rainbow
|
||||
float frequency = 0.026;
|
||||
for (int x = 0; x < 240; x++) {
|
||||
color[0] = sin(frequency*x + 0) * 127 + 128;
|
||||
color[1] = sin(frequency*x + 2) * 127 + 128;
|
||||
color[2] = sin(frequency*x + 4) * 127 + 128;
|
||||
for (int y = 0; y < 240; y++) {
|
||||
if (x == 0 && y == 0) {
|
||||
GC9A01_write(color, sizeof(color));
|
||||
} else {
|
||||
GC9A01_write_continue(color, sizeof(color));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delay(1000);
|
||||
|
||||
// Checkerboard
|
||||
for (int x = 0; x < 240; x++) {
|
||||
for (int y = 0; y < 240; y++) {
|
||||
if ((x / 10) % 2 == (y / 10) % 2) {
|
||||
color[0] = 0xFF;
|
||||
color[1] = 0xFF;
|
||||
color[2] = 0xFF;
|
||||
} else {
|
||||
color[0] = 0x00;
|
||||
color[1] = 0x00;
|
||||
color[2] = 0x00;
|
||||
}
|
||||
if (x == 0 && y == 0) {
|
||||
GC9A01_write(color, sizeof(color));
|
||||
} else {
|
||||
GC9A01_write_continue(color, sizeof(color));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delay(1000);
|
||||
}
|
||||
*/
|
||||
|
||||
#define FONT_JUMPTABLE_BYTES 4
|
||||
|
||||
#define FONT_JUMPTABLE_MSB 0
|
||||
#define FONT_JUMPTABLE_LSB 1
|
||||
#define FONT_JUMPTABLE_SIZE 2
|
||||
#define FONT_JUMPTABLE_WIDTH 3
|
||||
#define FONT_JUMPTABLE_START 4
|
||||
|
||||
#define FONT_WIDTH_POS 0
|
||||
#define FONT_HEIGHT_POS 1
|
||||
#define FONT_FIRST_CHAR_POS 2
|
||||
#define FONT_CHAR_NUM_POS 3
|
||||
|
||||
int16_t font_get_str_width(const uint8_t *font, const char *str, uint8_t len, int8_t extra_spacing)
|
||||
{
|
||||
uint8_t first = font[FONT_FIRST_CHAR_POS];
|
||||
uint8_t chr_width;
|
||||
uint8_t str_width = 0;
|
||||
uint8_t w;
|
||||
|
||||
w = len;
|
||||
|
||||
while (w--) {
|
||||
chr_width = font[FONT_JUMPTABLE_START + (str[w] - first) * FONT_JUMPTABLE_BYTES + FONT_JUMPTABLE_WIDTH];
|
||||
str_width += chr_width;
|
||||
}
|
||||
|
||||
str_width += extra_spacing * (len - 1);
|
||||
|
||||
return str_width;
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
|
||||
Serial.println("starting...");
|
||||
|
||||
delay(50);
|
||||
|
||||
bus->begin(90000000);
|
||||
|
||||
if (!disp->begin()) {
|
||||
Serial.println("failed to start disp");
|
||||
}
|
||||
|
||||
dout->begin();
|
||||
dout->fillScreen(BLACK);
|
||||
dout->flush();
|
||||
|
||||
drot->begin();
|
||||
drot->setFont(u8g2_font_cubic11_h_cjk); // u8g2_font_spleen16x32_mr
|
||||
drot->setTextSize(TEXT_SIZE);
|
||||
}
|
||||
|
||||
void rotate_letter(uint8_t idx, int16_t rot, int16_t out_x, int16_t out_y, uint16_t color)
|
||||
{
|
||||
int16_t x, y;
|
||||
int16_t nx, ny;
|
||||
int16_t sx, sy;
|
||||
|
||||
int16_t start_x, start_y;
|
||||
|
||||
int16_t x_width;
|
||||
|
||||
uint16_t *src, *dst;
|
||||
uint16_t src_pxl;
|
||||
uint16_t bgcolor = CYAN;
|
||||
|
||||
// clear the rotation buffer
|
||||
drot->fillScreen(CYAN);
|
||||
|
||||
// print the letter to the center of the rotation buffer
|
||||
drot->setCursor(0, TEXT_SIZE * 10);
|
||||
drot->setTextColor(color);
|
||||
drot->print(name[idx]);
|
||||
x_width = drot->getCursorX() - TEXT_SIZE;
|
||||
|
||||
// framebuffers
|
||||
src = drot->getFramebuffer();
|
||||
dst = dout->getFramebuffer();
|
||||
|
||||
// position
|
||||
start_x = out_x + 120;
|
||||
start_y = out_y + 120;
|
||||
|
||||
// rotate+copy the buffer
|
||||
for (y = 0; y < ROT_SIZE; y++) {
|
||||
for (x = 0; x < x_width; x++) {
|
||||
src_pxl = src[x + (y * ROT_SIZE)];
|
||||
sx = x + 1 - (x_width >> 1);
|
||||
sy = y - (ROT_SIZE/2) + 1;
|
||||
if (src_pxl != bgcolor) {
|
||||
nx = ((sx * cos1(rot)) - (sy * sin1(rot))) >> 15;
|
||||
ny = ((sx * sin1(rot)) + (sy * cos1(rot))) >> 15;
|
||||
|
||||
nx += start_x;
|
||||
ny += start_y;
|
||||
|
||||
if ((nx >= 0) && (nx < 240)) {
|
||||
if ((ny >= 0) && (ny < 240)) {
|
||||
dst[nx + (ny*240)] = src_pxl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int16_t rot = 0;
|
||||
|
||||
void loop()
|
||||
{
|
||||
uint16_t hue;
|
||||
|
||||
hsv.h += 24;
|
||||
|
||||
// background fill
|
||||
hue = hsv.h + 512;
|
||||
hsv.h %= 1536;
|
||||
hsv2rgb_8b(hue, 255, 128, &rgb.r, &rgb.g, &rgb.b);
|
||||
// dout->fillScreen(dout->color565(rgb.r, rgb.g, rgb.b));
|
||||
dout->fillScreen(BLACK);
|
||||
|
||||
hue = hsv.h;
|
||||
|
||||
for (int8_t i = 120; i > 0; i--) {
|
||||
hue += 2;
|
||||
hue %= 1536;
|
||||
hsv2rgb_8b(hue, 220, (i * 2), &rgb.r, &rgb.g, &rgb.b);
|
||||
|
||||
dout->drawCircle(120, 120, i, dout->color565(rgb.r, rgb.g, rgb.b));
|
||||
}
|
||||
|
||||
hue = hsv.h + 768;
|
||||
hue %= 1536;
|
||||
hsv2rgb_8b(hue, 224, 64, &rgb.r, &rgb.g, &rgb.b);
|
||||
|
||||
rot += 420 - 69;
|
||||
|
||||
int16_t x, y;
|
||||
int16_t d;
|
||||
d = rot;
|
||||
for (uint8_t i = 0; i < strlen(name); i++) {
|
||||
x = cos1(d);
|
||||
x = (x >> 9) + (x >> 11) + (x >> 12);
|
||||
|
||||
y = sin1(d); // sin1(d) * 21) / 32;
|
||||
y = (y >> 9) + (y >> 11) + (y >> 12);
|
||||
|
||||
rotate_letter(i, d + 0x6000, x, y, dout->color565(rgb.r, rgb.g, rgb.b));
|
||||
// d -= 9; // for 7-bit version
|
||||
d -= LETTER_SPACING; // for 15-bit version
|
||||
}
|
||||
|
||||
dout->flush();
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
/**
|
||||
* Example for a sine/cosine table lookup
|
||||
* Implementation of sin1() / cos1().
|
||||
* We "outsource" this implementation so that the precompiler constants/macros
|
||||
* are only defined here.
|
||||
*
|
||||
* @file sin1.c
|
||||
* @author stfwi
|
||||
**/
|
||||
|
||||
#include "sin1.h"
|
||||
|
||||
/*
|
||||
* The number of bits of our data type: here 16 (sizeof operator returns bytes).
|
||||
*/
|
||||
#define INT16_BITS (8 * sizeof(int16_t))
|
||||
#ifndef INT16_MAX
|
||||
#define INT16_MAX ((1<<(INT16_BITS-1))-1)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* "5 bit" large table = 32 values. The mask: all bit belonging to the table
|
||||
* are 1, the all above 0.
|
||||
*/
|
||||
#define TABLE_BITS (5)
|
||||
#define TABLE_SIZE (1<<TABLE_BITS)
|
||||
#define TABLE_MASK (TABLE_SIZE-1)
|
||||
|
||||
/*
|
||||
* The lookup table is to 90DEG, the input can be -360 to 360 DEG, where negative
|
||||
* values are transformed to positive before further processing. We need two
|
||||
* additional bits (*4) to represent 360 DEG:
|
||||
*/
|
||||
#define LOOKUP_BITS (TABLE_BITS+2)
|
||||
#define LOOKUP_MASK ((1<<LOOKUP_BITS)-1)
|
||||
#define FLIP_BIT (1<<TABLE_BITS)
|
||||
#define NEGATE_BIT (1<<(TABLE_BITS+1))
|
||||
#define INTERP_BITS (INT16_BITS-1-LOOKUP_BITS)
|
||||
#define INTERP_MASK ((1<<INTERP_BITS)-1)
|
||||
|
||||
/**
|
||||
* "5 bit" lookup table for the offsets. These are the sines for exactly
|
||||
* at 0deg, 11.25deg, 22.5deg etc. The values are from -1 to 1 in Q15.
|
||||
*/
|
||||
static int16_t sin90[TABLE_SIZE+1] = {
|
||||
0x0000,0x0647,0x0c8b,0x12c7,0x18f8,0x1f19,0x2527,0x2b1e,
|
||||
0x30fb,0x36b9,0x3c56,0x41cd,0x471c,0x4c3f,0x5133,0x55f4,
|
||||
0x5a81,0x5ed6,0x62f1,0x66ce,0x6a6c,0x6dc9,0x70e1,0x73b5,
|
||||
0x7640,0x7883,0x7a7c,0x7c29,0x7d89,0x7e9c,0x7f61,0x7fd7,
|
||||
0x7fff
|
||||
};
|
||||
|
||||
/**
|
||||
* Sine calculation using interpolated table lookup.
|
||||
* Instead of radiants or degrees we use "turns" here. Means this
|
||||
* sine does NOT return one phase for 0 to 2*PI, but for 0 to 1.
|
||||
* Input: -1 to 1 as int16 Q15 == -32768 to 32767.
|
||||
* Output: -1 to 1 as int16 Q15 == -32768 to 32767.
|
||||
*
|
||||
* See the full description at www.AtWillys.de for the detailed
|
||||
* explanation.
|
||||
*
|
||||
* @param int16_t angle Q15
|
||||
* @return int16_t Q15
|
||||
*/
|
||||
int16_t sin1(int16_t angle)
|
||||
{
|
||||
int16_t v0, v1;
|
||||
if(angle < 0) { angle += INT16_MAX; angle += 1; }
|
||||
v0 = (angle >> INTERP_BITS);
|
||||
if(v0 & FLIP_BIT) { v0 = ~v0; v1 = ~angle; } else { v1 = angle; }
|
||||
v0 &= TABLE_MASK;
|
||||
v1 = sin90[v0] + (int16_t) (((int32_t) (sin90[v0+1]-sin90[v0]) * (v1 & INTERP_MASK)) >> INTERP_BITS);
|
||||
if((angle >> INTERP_BITS) & NEGATE_BIT) v1 = -v1;
|
||||
return v1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cosine calculation using interpolated table lookup.
|
||||
* Instead of radiants or degrees we use "turns" here. Means this
|
||||
* cosine does NOT return one phase for 0 to 2*PI, but for 0 to 1.
|
||||
* Input: -1 to 1 as int16 Q15 == -32768 to 32767.
|
||||
* Output: -1 to 1 as int16 Q15 == -32768 to 32767.
|
||||
*
|
||||
* @param int16_t angle Q15
|
||||
* @return int16_t Q15
|
||||
*/
|
||||
int16_t cos1(int16_t angle)
|
||||
{
|
||||
if(angle < 0) { angle += INT16_MAX; angle += 1; }
|
||||
return sin1(angle - (int16_t)(((int32_t)INT16_MAX * 3) / 4));
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
/**
|
||||
* Example for a sine/cosine table lookup
|
||||
*
|
||||
* butchered by true to work in 7 bits (int8_t, two turns), and to fix cos8 function
|
||||
* copied / inspired more or less from
|
||||
* https://www.atwillys.de/content/cc/sine-lookup-for-embedded-in-c/
|
||||
**/
|
||||
|
||||
#include "sin7.h"
|
||||
|
||||
/*
|
||||
* The number of bits of our data type: here 8 (sizeof operator returns bytes).
|
||||
*/
|
||||
#define INT8_BITS (8 * sizeof(int8_t))
|
||||
#ifndef INT8_MAX
|
||||
#define INT8_MAX ((1<<(INT8_BITS-1))-1)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* "5 bit" large table = 32 values. The mask: all bit belonging to the table
|
||||
* are 1, the all above 0.
|
||||
*/
|
||||
#define TABLE_BITS (5)
|
||||
#define TABLE_SIZE (1<<TABLE_BITS)
|
||||
#define TABLE_MASK (TABLE_SIZE-1)
|
||||
|
||||
/*
|
||||
* The lookup table is to 90DEG, the input can be -360 to 360 DEG, where negative
|
||||
* values are transformed to positive before further processing. We need two
|
||||
* additional bits (*4) to represent 360 DEG:
|
||||
*/
|
||||
#define LOOKUP_BITS (TABLE_BITS+2)
|
||||
#define LOOKUP_MASK ((1<<LOOKUP_BITS)-1)
|
||||
#define FLIP_BIT (1<<TABLE_BITS)
|
||||
#define NEGATE_BIT (1<<(TABLE_BITS+1))
|
||||
#define INTERP_BITS (INT8_BITS-1-LOOKUP_BITS)
|
||||
#define INTERP_MASK ((1<<INTERP_BITS)-1)
|
||||
|
||||
/**
|
||||
* "5 bit" lookup table for the offsets. These are the sines for exactly
|
||||
* at 0deg, 11.25deg, 22.5deg etc. The values are from -1 to 1 in Q8?.
|
||||
*/
|
||||
static const int8_t sin90[TABLE_SIZE + 1] = {
|
||||
0x00, 0x06, 0x0c, 0x12, 0x18, 0x1e, 0x24, 0x2a,
|
||||
0x30, 0x36, 0x3b, 0x41, 0x46, 0x4b, 0x50, 0x55,
|
||||
0x59, 0x5e, 0x62, 0x66, 0x69, 0x6c, 0x70, 0x72,
|
||||
0x75, 0x77, 0x79, 0x7b, 0x7c, 0x7d, 0x7e, 0x7e,
|
||||
0x7f
|
||||
};
|
||||
|
||||
/**
|
||||
* Sine calculation using interpolated table lookup.
|
||||
* Instead of radians or degrees we use "turns" here. Means this
|
||||
* sine does NOT return one phase for 0 to 2*PI, but for 0 to 1.
|
||||
* Input: -1 to 1 as int8 == -128 to 127
|
||||
* Output: -1 to 1 as int8 == -128 to 127
|
||||
*
|
||||
* @param int8_t angle
|
||||
* @return int8_t
|
||||
*/
|
||||
int8_t sin7(int8_t angle)
|
||||
{
|
||||
int8_t v0, v1;
|
||||
|
||||
if(angle < 0) {
|
||||
angle += INT8_MAX;
|
||||
angle += 1;
|
||||
}
|
||||
|
||||
v0 = (angle >> INTERP_BITS);
|
||||
|
||||
if (v0 & FLIP_BIT) {
|
||||
v0 = ~v0;
|
||||
v1 = ~angle;
|
||||
} else {
|
||||
v1 = angle;
|
||||
}
|
||||
|
||||
v0 &= TABLE_MASK;
|
||||
|
||||
v1 = sin90[v0] + (int8_t)(((int16_t)(sin90[v0+1]-sin90[v0]) * (v1 & INTERP_MASK)) >> INTERP_BITS);
|
||||
|
||||
if((angle >> INTERP_BITS) & NEGATE_BIT) {
|
||||
v1 = -v1;
|
||||
}
|
||||
|
||||
return v1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cosine calculation using interpolated table lookup.
|
||||
* Instead of radians or degrees we use "turns" here. Means this
|
||||
* cosine does NOT return one phase for 0 to 2*PI, but for 0 to 1.
|
||||
* Input: -1 to 1 as int8 == -128 to 127
|
||||
* Output: -1 to 1 as int8 == -128 to 127
|
||||
*
|
||||
* @param int8_t angle
|
||||
* @return int8_t
|
||||
*/
|
||||
int8_t cos7(int8_t angle)
|
||||
{
|
||||
if (angle < 0) {
|
||||
angle += INT8_MAX;
|
||||
angle += 1;
|
||||
}
|
||||
|
||||
return sin7(angle - ((INT8_MAX * 3) / 4));
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
This directory is intended for PlatformIO Test Runner and project tests.
|
||||
|
||||
Unit Testing is a software testing method by which individual units of
|
||||
source code, sets of one or more MCU program modules together with associated
|
||||
control data, usage procedures, and operating procedures, are tested to
|
||||
determine whether they are fit for use. Unit testing finds problems early
|
||||
in the development cycle.
|
||||
|
||||
More information about PlatformIO Unit Testing:
|
||||
- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
|
||||
u8g2_fonts.h
|
||||
|
||||
Several definitions for the fonts, included and required for u8g2_fonts.c.
|
||||
If the u8g2_fonts.c file is copied from u8g2 project, replace the include
|
||||
from "u8g2.h" to "u8g2_fonts.h"
|
||||
|
||||
U8g2 for Adafruit GFX Lib (https://github.com/olikraus/U8g2_for_Adafruit_GFX)
|
||||
|
||||
Copyright (c) 2018, olikraus@gmail.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _u8g2_fonts_h
|
||||
#define _u8g2_fonts_h
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __GNUC__
|
||||
# define U8X8_NOINLINE __attribute__((noinline))
|
||||
# define U8X8_SECTION(name) __attribute__ ((section (name)))
|
||||
# define U8X8_UNUSED __attribute__((unused))
|
||||
#else
|
||||
# define U8X8_SECTION(name)
|
||||
# define U8X8_NOINLINE
|
||||
# define U8X8_UNUSED
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && defined(__AVR__)
|
||||
# define U8X8_FONT_SECTION(name) U8X8_SECTION(".progmem." name)
|
||||
# define u8x8_pgm_read(adr) pgm_read_byte_near(adr)
|
||||
# define U8X8_PROGMEM PROGMEM
|
||||
#endif
|
||||
|
||||
#ifndef U8X8_FONT_SECTION
|
||||
# define U8X8_FONT_SECTION(name)
|
||||
#endif
|
||||
|
||||
#ifndef u8x8_pgm_read
|
||||
# define u8x8_pgm_read(adr) (*(const uint8_t *)(adr))
|
||||
#endif
|
||||
|
||||
#ifndef U8X8_PROGMEM
|
||||
# define U8X8_PROGMEM
|
||||
#endif
|
||||
|
||||
#define U8G2_FONT_SECTION(name) U8X8_FONT_SECTION(name)
|
||||
|
||||
/* the macro U8G2_USE_LARGE_FONTS enables large fonts (>32K) */
|
||||
/* it can be enabled for those uC supporting larger arrays */
|
||||
#if defined(unix) || defined(__arm__) || defined(__arc__) || defined(ESP8266) || defined(ESP_PLATFORM)
|
||||
#ifndef U8G2_USE_LARGE_FONTS
|
||||
#define U8G2_USE_LARGE_FONTS
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* _u8g2_fonts_h */
|
||||
|
Loading…
Reference in New Issue