Skip to content
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

9 display emulator #20

Merged
merged 5 commits into from
Oct 9, 2022
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
30 changes: 23 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# SSD1351 Driver Library
Driver library for the SSD1351 128x128 RGB OLED Display intended for generic use under C in any microcontroller.
Unit testing is implemented with Ceedling.
Driver library for the SSD1351 128x128 RGB OLED Display intended for generic use with C in any microcontroller/device.
Includes an emulator to run and test programs that use this library on Windows.

*Remember to configure the ssd1351.h file GPIO, SPI definitions according to your own hardware*

[Check the blog entry](https://gecko05.github.io/2019/06/23/rgb-library.html)

Added support for:
Features:
* Drawing sprites
* Importing sprites from a .bmp file made in Aseprite
* Formatted string printing
Expand All @@ -16,6 +16,7 @@ Added support for:
* Drawing circles and filled circles
* Display configuration
* RGB color encoding
* Screen emulator for Windows

To Do:
* Extend Display configurations such as color depth, frequency, etc.
Expand All @@ -34,6 +35,18 @@ Note that the color palette used in Aseprite will be translated to the equivalen
Check the releases to find a sample project that uses this library for the following boards:
* [ST Nucleo L152RE](https://github.com/Gecko05/SSD1351-Driver-Library/releases)

# Running the emulator

An emulator written in Go is located under SSD1351_Emulator. To use it simply run the following command inside the directory:
```
go run .
```
It will open a socket on port 9988 and listen for incoming screen data. To see it in action, simply compile and run the program under example_with_emulator_WIN.
Not that this example program runs only on Windows.

See the releases section if you're only interested in the binaries for both the demo program and the emulator.
[Emulator and example binaries](https://github.com/Gecko05/SSD1351-Driver-Library/releases/tag/v1.1.0)

# Demo

Sample code includes three demos; printing, lines, circles and a sprite
Expand All @@ -43,6 +56,8 @@ Sample code includes three demos; printing, lines, circles and a sprite
#include "math.h"
#include "stdlib.h"

#define DEMO_RECTANGLES

int main(){
SSD1351_init();
SSD1351_fill(COLOR_BLACK);
Expand All @@ -64,8 +79,8 @@ int main(){
// D E M O P R I N T
SSD1351_set_cursor(0, 0);
SSD1351_printf(SSD1351_get_rgb(r, g, b), med_font, "Hello worldI spent \n%i %s\n", 17, "dollars");
SSD1351_printf(COLOR_RED, small_font, "\nIn this screen");
SSD1351_printf(SSD1351_get_rgb(245, 255, 20), big_font, "\nSTM32");
SSD1351_printf(COLOR_RED, small_font, "\nfor this");
SSD1351_printf(SSD1351_get_rgb(245, 255, 20), big_font, "\nSSD1351");
if (gd){
g+=3;
b-=3;
Expand All @@ -81,9 +96,9 @@ int main(){
gd = !gd;
}
#endif // DEMO_PRINT
#ifdef DEMO RECTANGLES
#ifdef DEMO_RECTANGLES
// D E M O R E C T A N G L E S
for (int i = 128; i > 0;i-=12){
for (int i = 128; i > 0;i-=12){
SSD1351_draw_filled_rect( 64 - i/2, 64 - i/2, i, i, 0x1111 + rand());
}
#endif // DEMO_RECTANGLES
Expand Down Expand Up @@ -130,6 +145,7 @@ int main(){
SSD1351_draw_sprite(0, 0, &sprite0);
#endif // DEMO_SPRITES
SSD1351_update();
HAL_Delay(33);
}
}
```
18 changes: 18 additions & 0 deletions SSD1351_Emulator/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
module SSD1351_renderer

go 1.18

require gioui.org v0.0.0-20221004231135-80196f3c3ed3

require (
eliasnaur.com/font v0.0.0-20220215125817-de715634c840 // indirect
gioui.org/cpu v0.0.0-20210817075930-8d6a761490d2 // indirect
gioui.org/shader v1.0.6 // indirect
github.com/benoitkugler/textlayout v0.1.3 // indirect
github.com/gioui/uax v0.2.1-0.20220819135011-cda973fac06d // indirect
github.com/go-text/typesetting v0.0.0-20220411150340-35994bc27a7b // indirect
golang.org/x/exp/shiny v0.0.0-20220906200021-fcb1a314c389 // indirect
golang.org/x/image v0.0.0-20220902085622-e7cb96979f69 // indirect
golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64 // indirect
golang.org/x/text v0.3.7 // indirect
)
35 changes: 35 additions & 0 deletions SSD1351_Emulator/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
eliasnaur.com/font v0.0.0-20220215125817-de715634c840 h1:HovVBbKkUnf7OFR0qZy1PRB5CIabj+k5VRUDiIboM9c=
eliasnaur.com/font v0.0.0-20220215125817-de715634c840/go.mod h1:OYVuxibdk9OSLX8vAqydtRPP87PyTFcT9uH3MlEGBQA=
gioui.org v0.0.0-20221004231135-80196f3c3ed3 h1:41UBL6RQpfauddgYpcIDLPxbHj/Sixa82dqWYdUdK4s=
gioui.org v0.0.0-20221004231135-80196f3c3ed3/go.mod h1:GN091SCcGAfHfQiSOetXx7Abdy+8nmONj0ZN63Xxf7w=
gioui.org/cpu v0.0.0-20210808092351-bfe733dd3334/go.mod h1:A8M0Cn5o+vY5LTMlnRoK3O5kG+rH0kWfJjeKd9QpBmQ=
gioui.org/cpu v0.0.0-20210817075930-8d6a761490d2 h1:AGDDxsJE1RpcXTAxPG2B4jrwVUJGFDjINIPi1jtO6pc=
gioui.org/cpu v0.0.0-20210817075930-8d6a761490d2/go.mod h1:A8M0Cn5o+vY5LTMlnRoK3O5kG+rH0kWfJjeKd9QpBmQ=
gioui.org/shader v1.0.6 h1:cvZmU+eODFR2545X+/8XucgZdTtEjR3QWW6W65b0q5Y=
gioui.org/shader v1.0.6/go.mod h1:mWdiME581d/kV7/iEhLmUgUK5iZ09XR5XpduXzbePVM=
github.com/benoitkugler/pstokenizer v1.0.0/go.mod h1:l1G2Voirz0q/jj0TQfabNxVsa8HZXh/VMxFSRALWTiE=
github.com/benoitkugler/textlayout v0.0.5/go.mod h1:puH4v13Uz7uIhIH0XMk5jgc8U3MXcn5r3VlV9K8n0D8=
github.com/benoitkugler/textlayout v0.1.3 h1:Jv0E28xDkke3KrWle90yOLtBmZsUqXLBy70lZRfbKN0=
github.com/benoitkugler/textlayout v0.1.3/go.mod h1:o+1hFV+JSHBC9qNLIuwVoLedERU7sBPgEFcuSgfvi/w=
github.com/benoitkugler/textlayout-testdata v0.1.1 h1:AvFxBxpfrQd8v55qH59mZOJOQjtD6K2SFe9/HvnIbJk=
github.com/gioui/uax v0.2.1-0.20220819135011-cda973fac06d h1:ro1W5kY1pVBLHy4GokZUfr9cl7ewZhAiT5WsXqFDYE4=
github.com/gioui/uax v0.2.1-0.20220819135011-cda973fac06d/go.mod h1:b6uGh9ySJPVQG/RdiI88bE5sUGDk6vzzRujv1BAeuJc=
github.com/go-text/typesetting v0.0.0-20220411150340-35994bc27a7b h1:WINlj3ANt+CVrO2B4NGDHRlPvEWZPxjhb7z+JKypwXI=
github.com/go-text/typesetting v0.0.0-20220411150340-35994bc27a7b/go.mod h1:ZNYu5saGoMOqtkVH5T8onTwhzenDUVszI+5WFHJRaxQ=
golang.org/x/exp/shiny v0.0.0-20220906200021-fcb1a314c389 h1:RJgV139fC8cnvcf8+MhE9Idc9wzOfUPhGY7q7R0YTvQ=
golang.org/x/exp/shiny v0.0.0-20220906200021-fcb1a314c389/go.mod h1:VjAR7z0ngyATZTELrBSkxOOHhhlnVUxDye4mcjx5h/8=
golang.org/x/image v0.0.0-20210504121937-7319ad40d33e/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20210607152325-775e3b0c77b9/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
golang.org/x/image v0.0.0-20220902085622-e7cb96979f69 h1:Lj6HJGCSn5AjxRAH2+r35Mir4icalbqku+CLUtjnvXY=
golang.org/x/image v0.0.0-20220902085622-e7cb96979f69/go.mod h1:doUCurBvlfPMKfmIpRIywoHmhN3VyhnoFDbvIEWF4hY=
golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64 h1:UiNENfZ8gDvpiWw7IpOMQ27spWmThO1RwwdQVbJahJM=
golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
125 changes: 125 additions & 0 deletions SSD1351_Emulator/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
package main

import (
"fmt"
"image"
"image/color"
"log"
"net"
"os"
"time"

"gioui.org/app"
"gioui.org/f32"

"gioui.org/io/system"
"gioui.org/layout"
"gioui.org/op"
"gioui.org/op/paint"
)

const (
SERVER_HOST = "localhost"
SERVER_PORT = "9988"
SERVER_TYPE = "tcp"
)

var screenBuffer []byte

func processClient(connection net.Conn) {
buffer := make([]byte, 32768)
mLen, err := connection.Read(buffer)
if err != nil {
fmt.Println("Error reading:", err.Error())
}
// Look for whole frames
if mLen == 32768 {
screenBuffer = buffer[:32768]
}
connection.Close()
}

func initServer() {
fmt.Println("Server Running...")
server, err := net.Listen(SERVER_TYPE, SERVER_HOST+":"+SERVER_PORT)
if err != nil {
fmt.Println("Error listening:", err.Error())
os.Exit(1)
}
defer server.Close()
fmt.Println("Listening on " + SERVER_HOST + ":" + SERVER_PORT)
fmt.Println("Waiting for client...")
for {
connection, err := server.Accept()
if err != nil {
fmt.Println("Error accepting: ", err.Error())
os.Exit(1)
}
processClient(connection)
}
}

func main() {
go initServer()
go func() {
w := app.NewWindow(app.Size(256, 256), app.MinSize(256, 256), app.MaxSize(256, 256))
go func() {
timer1 := time.NewTicker(time.Second / 30)
for {
<-timer1.C
w.Invalidate()
}
}()
err := run(w)
if err != nil {
log.Fatal(err)
}
os.Exit(0)
}()
app.Main()
}

func drawImage(ops *op.Ops, img image.Image, w *app.Window) {
imageOp := paint.NewImageOp(img)
imageOp.Add(ops)
t := op.Affine(f32.Affine2D{}.Scale(f32.Pt(0, 0), f32.Pt(2, 2)))
t.Push(ops)
paint.PaintOp{}.Add(ops)
}

func run(w *app.Window) error {
var ops op.Ops
for {
e := <-w.Events()
switch e := e.(type) {
case system.DestroyEvent:
return e.Err
case system.FrameEvent:
gtx := layout.NewContext(&ops, e)

minPoint := image.Point{0, 0}
maxPoint := image.Point{128, 128}
rect := image.Rectangle{minPoint, maxPoint}
myImage := image.NewNRGBA(rect)
for i := 0; i < 32768; i += 2 {
if len(screenBuffer) == 32768 {
// 1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4
// b b b b b g g g g g g r r r r r
r := screenBuffer[i+1] & 0x1F << 3
b := screenBuffer[i] & 0xF8
g := (((screenBuffer[i] & 0x07) << 4) | ((screenBuffer[i+1] & 0xE0) >> 5)) << 1
newColor := color.NRGBA{r, g, b, 255}
// The image is flipped horizontally
newI := 32767 - i
myImage.SetNRGBA((newI/2)%128, int((i/2)/128), newColor)
} else {
newColor := color.NRGBA{0, 200, 0, 255}
myImage.SetNRGBA((i/2)%128, int((i/2)/128), newColor)
}
}
drawImage(gtx.Ops, myImage, w)

e.Frame(gtx.Ops)
}
}
}
2 changes: 1 addition & 1 deletion example/makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
CC = gcc
SRC_DIR = ../src
HAL_DIR = ../example
CFLAGS = -Wextra -g -I$(SRC_DIR)
CFLAGS = -Wextra -g -I$(SRC_DIR) -I.
INCLUDE = -I/../example
DEPS = $(SRC_DIR)/ssd1351.h $(SRC_DIR)/fonts.h $(SRC_DIR)/sprites.h $(SRC_DIR)/color_palette.h $(HAL_DIR)/myHAL.h
OBJS = $(SRC_DIR)/ssd1351.o $(SRC_DIR)/color_palette.o $(SRC_DIR)/fonts.o $(SRC_DIR)/sprites.o $(HAL_DIR)/myHAL.o
Expand Down
13 changes: 8 additions & 5 deletions example/myHAL.c
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
#include "myHAL.h"

// For demonstration purposes
#include "stdio.h"

#ifdef _WIN64
#include "time.h"

void SPI_TXBuffer(uint8_t *buffer, uint32_t len) {
// do nothing
printf("I'm sending a buffer\n");
}

void SPI_TXByte(uint8_t data) {
// do nothing
void SPI_TXByte(uint8_t* data) {
printf("I'm sending a byte\n");
}

void GPIO_SetPin(uint16_t Port, uint16_t Pin) {
// do nothing
printf("I'm setting a pin\n");
}

void GPIO_ResetPin(uint16_t Port, uint16_t Pin) {
// do nothing
printf("I'm resetting a pin\n");
}

void HAL_Delay(uint16_t ms) {
Expand Down
2 changes: 1 addition & 1 deletion example/myHAL.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

void SPI_TXBuffer(uint8_t *buffer, uint32_t len);

void SPI_TXByte(uint8_t data);
void SPI_TXByte(uint8_t* data);

void GPIO_SetPin(uint16_t Port, uint16_t Pin);

Expand Down
Loading