mirror of
https://github.com/Crocmagnon/display-epaper.git
synced 2024-12-23 12:31:47 +01:00
display transport
This commit is contained in:
parent
8be7b20062
commit
452ac199d0
8 changed files with 199 additions and 93 deletions
108
epd/epd.go
108
epd/epd.go
|
@ -45,48 +45,9 @@ func New() (*EPD, error) {
|
|||
partFlag: 1,
|
||||
}
|
||||
|
||||
if err := epd.resetPin.Out(gpio.Low); err != nil {
|
||||
return nil, fmt.Errorf("setting reset pin to low: %w", err)
|
||||
}
|
||||
if err := epd.dcPin.Out(gpio.Low); err != nil {
|
||||
return nil, fmt.Errorf("setting dc pin to low: %w", err)
|
||||
}
|
||||
if err := epd.csPin.Out(gpio.Low); err != nil {
|
||||
return nil, fmt.Errorf("setting cs pin to low: %w", err)
|
||||
}
|
||||
if err := epd.pwrPin.Out(gpio.High); err != nil {
|
||||
return nil, fmt.Errorf("setting pwr pin to low: %w", err)
|
||||
}
|
||||
|
||||
var err error
|
||||
|
||||
if epd.spiReg, err = spireg.Open("0"); err != nil {
|
||||
return nil, fmt.Errorf("opening SPI: %w", err)
|
||||
}
|
||||
|
||||
c, err := epd.spiReg.Connect(4*physic.MegaHertz, spi.Mode0, 8)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("connecting to SPI: %w", err)
|
||||
}
|
||||
|
||||
epd.spi = c
|
||||
|
||||
return epd, nil
|
||||
}
|
||||
|
||||
func (e *EPD) turnOff() error {
|
||||
log.Println("turning off...")
|
||||
if err := e.spiReg.Close(); err != nil {
|
||||
return fmt.Errorf("closing SPI: %w", err)
|
||||
}
|
||||
|
||||
e.resetPin.Out(gpio.Low)
|
||||
e.dcPin.Out(gpio.Low)
|
||||
e.pwrPin.Out(gpio.Low)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *EPD) reset() {
|
||||
e.resetPin.Out(gpio.High)
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
|
@ -97,7 +58,6 @@ func (e *EPD) reset() {
|
|||
}
|
||||
|
||||
func (e *EPD) sendCommand(cmd byte) {
|
||||
log.Printf("sending command 0x%02X\n", cmd)
|
||||
e.dcPin.Out(gpio.Low)
|
||||
e.csPin.Out(gpio.Low)
|
||||
if _, err := e.spiWrite([]byte{cmd}); err != nil {
|
||||
|
@ -116,7 +76,6 @@ func (e *EPD) sendData(data byte) {
|
|||
}
|
||||
|
||||
func (e *EPD) sendDataSlice(data []byte) {
|
||||
log.Printf("sending data slice %v\n", len(data))
|
||||
e.dcPin.Out(gpio.High)
|
||||
toSend := len(data)
|
||||
const maxSize = 4096
|
||||
|
@ -164,8 +123,44 @@ func (e *EPD) readBusy() {
|
|||
time.Sleep(200 * time.Millisecond)
|
||||
}
|
||||
|
||||
func (e *EPD) Init() {
|
||||
func (e *EPD) turnOn() error {
|
||||
log.Println("turning on")
|
||||
if err := e.resetPin.Out(gpio.Low); err != nil {
|
||||
return fmt.Errorf("setting reset pin to low: %w", err)
|
||||
}
|
||||
if err := e.dcPin.Out(gpio.Low); err != nil {
|
||||
return fmt.Errorf("setting dc pin to low: %w", err)
|
||||
}
|
||||
if err := e.csPin.Out(gpio.Low); err != nil {
|
||||
return fmt.Errorf("setting cs pin to low: %w", err)
|
||||
}
|
||||
if err := e.pwrPin.Out(gpio.High); err != nil {
|
||||
return fmt.Errorf("setting pwr pin to low: %w", err)
|
||||
}
|
||||
|
||||
var err error
|
||||
|
||||
if e.spiReg, err = spireg.Open("0"); err != nil {
|
||||
return fmt.Errorf("opening SPI: %w", err)
|
||||
}
|
||||
|
||||
c, err := e.spiReg.Connect(4*physic.MegaHertz, spi.Mode0, 8)
|
||||
if err != nil {
|
||||
return fmt.Errorf("connecting to SPI: %w", err)
|
||||
}
|
||||
|
||||
e.spi = c
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *EPD) Init() error {
|
||||
log.Println("initializing EPD")
|
||||
|
||||
if err := e.turnOn(); err != nil {
|
||||
return fmt.Errorf("turning on: %w", err)
|
||||
}
|
||||
|
||||
e.reset()
|
||||
|
||||
e.sendCommand(0x01)
|
||||
|
@ -192,10 +187,17 @@ func (e *EPD) Init() {
|
|||
|
||||
e.sendCommand(0x60)
|
||||
e.sendData(0x22)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *EPD) InitFast() {
|
||||
func (e *EPD) InitFast() error {
|
||||
log.Println("initializing Fast EPD")
|
||||
|
||||
if err := e.turnOn(); err != nil {
|
||||
return fmt.Errorf("turning on: %w", err)
|
||||
}
|
||||
|
||||
e.reset()
|
||||
|
||||
e.sendCommand(0x00)
|
||||
|
@ -216,13 +218,13 @@ func (e *EPD) InitFast() {
|
|||
|
||||
e.sendCommand(0x50)
|
||||
e.sendDataSlice([]byte{0x11, 0x07})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *EPD) Clear() {
|
||||
log.Println("clearing epd")
|
||||
e.Fill(White)
|
||||
|
||||
//e.Refresh()
|
||||
}
|
||||
|
||||
func (e *EPD) Refresh() {
|
||||
|
@ -233,7 +235,7 @@ func (e *EPD) Refresh() {
|
|||
}
|
||||
|
||||
func (e *EPD) Sleep() error {
|
||||
log.Println("sleeping...")
|
||||
log.Println("sleeping display...")
|
||||
e.sendCommand(0x02)
|
||||
e.readBusy()
|
||||
|
||||
|
@ -248,6 +250,19 @@ func (e *EPD) Sleep() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (e *EPD) turnOff() error {
|
||||
log.Println("turning off...")
|
||||
if err := e.spiReg.Close(); err != nil {
|
||||
return fmt.Errorf("closing SPI: %w", err)
|
||||
}
|
||||
|
||||
e.resetPin.Out(gpio.Low)
|
||||
e.dcPin.Out(gpio.Low)
|
||||
e.pwrPin.Out(gpio.Low)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type Color int
|
||||
|
||||
const (
|
||||
|
@ -270,7 +285,6 @@ func (e *EPD) Fill(c Color) {
|
|||
}
|
||||
|
||||
func (e *EPD) Send(black image.Image, red image.Image) {
|
||||
log.Println("drawing...")
|
||||
if black != nil {
|
||||
log.Println("sending black")
|
||||
e.sendCommand(0x10) // write bw data
|
||||
|
|
7
go.mod
7
go.mod
|
@ -11,4 +11,9 @@ require (
|
|||
golang.org/x/image v0.20.0
|
||||
)
|
||||
|
||||
require github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
|
||||
require (
|
||||
github.com/carlmjohnson/requests v0.24.2
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
|
||||
)
|
||||
|
||||
require golang.org/x/net v0.27.0 // indirect
|
||||
|
|
4
go.sum
4
go.sum
|
@ -1,3 +1,5 @@
|
|||
github.com/carlmjohnson/requests v0.24.2 h1:JDakhAmTIKL/qL/1P7Kkc2INGBJIkIFP6xUeUmPzLso=
|
||||
github.com/carlmjohnson/requests v0.24.2/go.mod h1:duYA/jDnyZ6f3xbcF5PpZ9N8clgopubP2nK5i6MVMhU=
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
||||
github.com/jonboulle/clockwork v0.3.0 h1:9BSCMi8C+0qdApAp4auwX0RkLGUjs956h0EkuQymUhg=
|
||||
|
@ -8,6 +10,8 @@ github.com/llgcode/ps v0.0.0-20210114104736-f4b0c5d1e02e h1:ZAvbj5hI/G/EbAYAcj4y
|
|||
github.com/llgcode/ps v0.0.0-20210114104736-f4b0c5d1e02e/go.mod h1:1l8ky+Ew27CMX29uG+a2hNOKpeNYEQjjtiALiBlFQbY=
|
||||
golang.org/x/image v0.20.0 h1:7cVCUjQwfL18gyBJOmYvptfSHS8Fb3YUDtfLIZ7Nbpw=
|
||||
golang.org/x/image v0.20.0/go.mod h1:0a88To4CYVBAHp5FXJm8o7QbUl37Vd85ply1vyD8auM=
|
||||
golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
|
||||
golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
|
||||
periph.io/x/conn/v3 v3.7.0 h1:f1EXLn4pkf7AEWwkol2gilCNZ0ElY+bxS4WE2PQXfrA=
|
||||
periph.io/x/conn/v3 v3.7.0/go.mod h1:ypY7UVxgDbP9PJGwFSVelRRagxyXYfttVh7hJZUHEhg=
|
||||
periph.io/x/host/v3 v3.8.2 h1:ayKUDzgUCN0g8+/xM9GTkWaOBhSLVcVHGTfjAOi8OsQ=
|
||||
|
|
36
img.go
36
img.go
|
@ -1,36 +1,38 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/Crocmagnon/display-epaper/epd"
|
||||
"github.com/Crocmagnon/display-epaper/transports"
|
||||
"github.com/llgcode/draw2d"
|
||||
"github.com/llgcode/draw2d/draw2dimg"
|
||||
"image"
|
||||
"image/color"
|
||||
)
|
||||
|
||||
func getBlack() (*image.RGBA, error) {
|
||||
func getBlack(ctx context.Context, transportsClient *transports.Client) (*image.RGBA, error) {
|
||||
passages, err := transportsClient.GetTCLPassages(ctx, 290)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("getting passages: %w", err)
|
||||
}
|
||||
|
||||
img := newWhite()
|
||||
|
||||
gc := draw2dimg.NewGraphicContext(img)
|
||||
|
||||
gc.SetFillRule(draw2d.FillRuleWinding)
|
||||
gc.SetFillColor(color.RGBA{0, 0, 0, 255})
|
||||
gc.SetStrokeColor(color.RGBA{0, 0, 0, 255})
|
||||
gc.SetLineWidth(2)
|
||||
|
||||
text(gc, "Hello, world", 18, 110, 50)
|
||||
|
||||
return img, nil
|
||||
}
|
||||
|
||||
func getRed() (*image.RGBA, error) {
|
||||
img := newBlack()
|
||||
gc := draw2dimg.NewGraphicContext(img)
|
||||
gc.SetFillColor(color.RGBA{0, 0, 0, 255})
|
||||
gc.SetStrokeColor(color.RGBA{255, 255, 255, 255})
|
||||
gc.SetLineWidth(2)
|
||||
|
||||
rect(gc, 10, 10, 50, 50)
|
||||
rect(gc, 60, 10, 100, 50)
|
||||
for i, passage := range passages.Passages {
|
||||
x := float64(10 + i*100)
|
||||
text(gc, passage.Ligne, 15, x, 20)
|
||||
for j, delay := range passage.Delays {
|
||||
y := float64(20 + (j+1)*30)
|
||||
text(gc, delay, 15, x, y)
|
||||
}
|
||||
}
|
||||
|
||||
return img, nil
|
||||
}
|
||||
|
@ -38,6 +40,8 @@ func getRed() (*image.RGBA, error) {
|
|||
func text(gc *draw2dimg.GraphicContext, s string, size, x, y float64) {
|
||||
gc.SetFontData(draw2d.FontData{Name: fontName})
|
||||
gc.SetFontSize(size)
|
||||
gc.FillStringAt(s, x, y)
|
||||
gc.SetLineWidth(2)
|
||||
gc.StrokeStringAt(s, x, y)
|
||||
}
|
||||
|
||||
|
|
11
main.go
11
main.go
|
@ -1,11 +1,14 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/Crocmagnon/display-epaper/transports"
|
||||
"github.com/golang/freetype/truetype"
|
||||
"github.com/llgcode/draw2d"
|
||||
_ "golang.org/x/image/bmp"
|
||||
"golang.org/x/image/font/gofont/goregular"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
const fontName = "default"
|
||||
|
@ -13,6 +16,8 @@ const fontName = "default"
|
|||
func main() {
|
||||
log.Println("starting...")
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
font, err := truetype.Parse(goregular.TTF)
|
||||
if err != nil {
|
||||
log.Fatalf("loading font: %v\n", err)
|
||||
|
@ -21,7 +26,11 @@ func main() {
|
|||
fontCache.Store(draw2d.FontData{Name: fontName}, font)
|
||||
draw2d.SetFontCache(fontCache)
|
||||
|
||||
if err := run(); err != nil {
|
||||
transportsClient := transports.New(nil, transports.Config{
|
||||
Authorization: os.Getenv("TRANSPORTS_AUTHORIZATION"),
|
||||
})
|
||||
|
||||
if err := run(ctx, transportsClient); err != nil {
|
||||
log.Fatal("error: ", err)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,23 +1,19 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/Crocmagnon/display-epaper/transports"
|
||||
"github.com/llgcode/draw2d/draw2dimg"
|
||||
"log"
|
||||
)
|
||||
|
||||
func run() error {
|
||||
img, err := getBlack()
|
||||
func run(ctx context.Context, transportsClient *transports.Client) error {
|
||||
img, err := getBlack(ctx, transportsClient)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
draw2dimg.SaveToPngFile("out/black.png", img)
|
||||
|
||||
img, err = getRed()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
draw2dimg.SaveToPngFile("out/red.png", img)
|
||||
|
||||
log.Println("done")
|
||||
|
||||
return nil
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/Crocmagnon/display-epaper/epd"
|
||||
"github.com/Crocmagnon/display-epaper/transports"
|
||||
"log"
|
||||
"periph.io/x/host/v3"
|
||||
"time"
|
||||
)
|
||||
|
||||
func run() error {
|
||||
func run(ctx context.Context, transportsClient *transports.Client) error {
|
||||
_, err := host.Init()
|
||||
if err != nil {
|
||||
return fmt.Errorf("initializing host: %w", err)
|
||||
|
@ -18,30 +21,45 @@ func run() error {
|
|||
return fmt.Errorf("initializing epd: %w", err)
|
||||
}
|
||||
|
||||
display.Init()
|
||||
//display.InitFast()
|
||||
display.Clear()
|
||||
display.Refresh()
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
log.Println("stopping because of context")
|
||||
return ctx.Err()
|
||||
default:
|
||||
}
|
||||
|
||||
black, err := getBlack()
|
||||
err = loop(ctx, display, transportsClient)
|
||||
if err != nil {
|
||||
log.Printf("error looping: %v\n", err)
|
||||
}
|
||||
|
||||
log.Println("time.Sleep(30s)")
|
||||
time.Sleep(30 * time.Second)
|
||||
}
|
||||
}
|
||||
|
||||
func loop(ctx context.Context, display *epd.EPD, transportsClient *transports.Client) error {
|
||||
defer func() {
|
||||
if err := display.Sleep(); err != nil {
|
||||
log.Printf("error sleeping: %v\n", err)
|
||||
}
|
||||
}()
|
||||
|
||||
err := display.Init()
|
||||
if err != nil {
|
||||
return fmt.Errorf("initializing display: %w", err)
|
||||
}
|
||||
|
||||
display.Clear()
|
||||
|
||||
black, err := getBlack(ctx, transportsClient)
|
||||
if err != nil {
|
||||
return fmt.Errorf("getting black: %w", err)
|
||||
}
|
||||
|
||||
red, err := getRed()
|
||||
if err != nil {
|
||||
return fmt.Errorf("getting red: %w", err)
|
||||
}
|
||||
|
||||
display.Send(black, red)
|
||||
|
||||
log.Println("sleeping...")
|
||||
|
||||
if err := display.Sleep(); err != nil {
|
||||
return fmt.Errorf("sleeping: %w", err)
|
||||
}
|
||||
|
||||
log.Println("done")
|
||||
display.Send(black, nil)
|
||||
display.Refresh()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
56
transports/transports.go
Normal file
56
transports/transports.go
Normal file
|
@ -0,0 +1,56 @@
|
|||
package transports
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/carlmjohnson/requests"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type Stop struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type Passage struct {
|
||||
Ligne string `json:"ligne"`
|
||||
Delays []string `json:"delais"`
|
||||
Destination Stop `json:"destination"`
|
||||
}
|
||||
|
||||
type Passages struct {
|
||||
Passages []Passage `json:"passages"`
|
||||
Stop Stop `json:"stop"`
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Authorization string
|
||||
}
|
||||
|
||||
type Client struct {
|
||||
client *http.Client
|
||||
config Config
|
||||
}
|
||||
|
||||
func New(httpClient *http.Client, config Config) *Client {
|
||||
if httpClient == nil {
|
||||
httpClient = &http.Client{}
|
||||
}
|
||||
return &Client{
|
||||
client: httpClient,
|
||||
config: config,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) GetTCLPassages(ctx context.Context, stop int) (res *Passages, err error) {
|
||||
err = requests.URL("https://tcl.augendre.info").
|
||||
Pathf("/stop/%v", stop).
|
||||
Header("Authorization", c.config.Authorization).
|
||||
Client(c.client).
|
||||
ToJSON(&res).
|
||||
Fetch(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("calling api: %w", err)
|
||||
}
|
||||
return res, nil
|
||||
}
|
Loading…
Reference in a new issue