1package main
  2
  3import (
  4	"fmt"
  5	"log"
  6	"syscall"
  7	"time"
  8
  9	"pihonclient/appdata"
 10	"pihonclient/extras"
 11	"pihonclient/phnparser"
 12	"pihonclient/renderer"
 13	"pihonclient/screendriver"
 14	"pihonclient/ui"
 15
 16	"github.com/warthog618/gpiod"
 17	"github.com/warthog618/gpiod/device/rpi"
 18)
 19
 20func checkError(error error) {
 21	if error != nil {
 22		log.Fatal(error)
 23	}
 24}
 25
 26func checkGPIOInitError(error error) {
 27	if error != nil {
 28		log.Fatal(fmt.Sprintf("RequestLine returned error: %s\n", error))
 29		if error == syscall.Errno(22) {
 30			log.Fatal("Note that the WithPullUp option requires kernel V5.5 or later - check your kernel version.")
 31		}
 32	}
 33}
 34
 35func selectBook() {
 36	// Read book
 37	phnparser.LoadBook(ui.UISelectionIndex)
 38	ui.UIDisplayedMenu = 2
 39	ui.UISelectionIndex = appdata.ReadBookData(phnparser.LoadedBookHash)
 40	ui.RenderUI()
 41}
 42
 43func checkIfBothButtonsArePressed(currentButton string) bool {
 44	if extras.LeftButtonState == true {
 45		if extras.RightButtonState == true {
 46			fmt.Println("Both buttons pressed!")
 47			ui.UISelectionIndex = ui.UISelectionIndexBuffer
 48			if ui.UIDisplayedMenu == 1 {
 49				selectBook()
 50				fmt.Println("Loaded a book!")
 51				return true
 52			} else if ui.UIDisplayedMenu == 2 {
 53				appdata.SaveBookData(phnparser.LoadedBookHash, ui.UISelectionIndex)
 54				ui.RenderUI()
 55				fmt.Println("Saved the position!")
 56				return true
 57			}
 58		}
 59	}
 60	return false
 61}
 62
 63func leftEventHandler(evt gpiod.LineEvent) {
 64	edge := "rising"
 65	extras.LeftButtonState = false
 66	if evt.Type == gpiod.LineEventFallingEdge {
 67		edge = "falling"
 68		extras.LeftButtonState = true
 69		extras.LeftButtonPressedTime = time.Now()
 70	}
 71	if edge == "rising" {
 72		if time.Now().Sub(extras.LeftButtonPressedTime).Seconds() >= extras.NavigationHoldDuration {
 73			if ui.UIDisplayedMenu == 2 {
 74				ui.UITopBarTitle = extras.FitWithinCharacterLimits(phnparser.MaxLengthOfLine-2, extras.GetCWD()+phnparser.LibraryPath)
 75				ui.UIDisplayedMenu = 1
 76				ui.UISelectionIndex = 0
 77				ui.UISelectionIndexBuffer = ui.UISelectionIndex
 78				ui.RenderUI()
 79			}
 80		}
 81	}
 82	if edge == "falling" {
 83		if checkIfBothButtonsArePressed("left") {
 84			return
 85		}
 86		fmt.Println("Left button pressed!")
 87		if ui.UIDisplayedMenu == 1 {
 88			if ui.UISelectionIndex > 0 {
 89				ui.UISelectionIndexBuffer = ui.UISelectionIndex
 90				ui.UISelectionIndex--
 91			}
 92			ui.RenderUI()
 93		} else if ui.UIDisplayedMenu == 2 {
 94			if ui.UISelectionIndex > 0 {
 95				ui.UISelectionIndexBuffer = ui.UISelectionIndex
 96				ui.UISelectionIndex--
 97			}
 98			ui.RenderUI()
 99		}
100	}
101}
102
103func rightEventHandler(evt gpiod.LineEvent) {
104	edge := "rising"
105	extras.RightButtonState = false
106	if evt.Type == gpiod.LineEventFallingEdge {
107		edge = "falling"
108		extras.RightButtonState = true
109	}
110	if edge == "falling" {
111		if checkIfBothButtonsArePressed("right") {
112			return
113		}
114		fmt.Println("Right button pressed!")
115		if ui.UIDisplayedMenu == 0 {
116			fmt.Println("Displaying library!")
117			// Library show
118			phnparser.ScanLibraryFolder()
119			ui.UITopBarTitle = extras.FitWithinCharacterLimits(phnparser.MaxLengthOfLine-2, extras.GetCWD()+phnparser.LibraryPath)
120			ui.UIDisplayedMenu = 1
121			ui.RenderUI()
122		} else if ui.UIDisplayedMenu == 1 {
123			if ui.UISelectionIndex < len(phnparser.LibraryHashes)-1 {
124				ui.UISelectionIndexBuffer = ui.UISelectionIndex
125				ui.UISelectionIndex++
126			}
127			ui.RenderUI()
128		} else if ui.UIDisplayedMenu == 2 {
129			if ui.UISelectionIndex*ui.UIMaxBookLines < len(phnparser.LoadedBookLines)-1 {
130				ui.UISelectionIndexBuffer = ui.UISelectionIndex
131				ui.UISelectionIndex++
132			}
133			ui.RenderUI()
134		}
135
136	}
137}
138
139func main() {
140	// Config
141	// Input
142	leftButtonPinRef := rpi.J8p11
143	rightButtonPinRef := rpi.J8p13
144	debouncingPeriod := 10 * time.Millisecond
145	extras.NavigationHoldDuration = 3
146	// Screen
147	renderer.ScreenCount = 2
148	renderer.ScreenWidth = 128
149	renderer.ScreenHeight = 64
150	// UI
151	ui.BuildVersion = "V2022.05.05"
152	ui.UIMargin = 1
153	ui.UITopBarHeight = 10
154	ui.UILineHeight = 8
155	ui.UIFontHorizontalSpacing = 9
156	ui.UIMaxBookLines = 6
157	// Display Driver
158	screendriver.I2CBuses = []string{"1", "4"}
159	// .phn Parser
160	phnparser.LibraryPath = "library/"
161	phnparser.MaxLengthOfLine = 28
162	// Appdata
163	appdata.DataPath = "data/"
164	// Extras
165	extras.CloudflareIP = "1.1.1.1"
166	// Code
167	// GPIO init
168	l, err := gpiod.RequestLine("gpiochip0", leftButtonPinRef, gpiod.WithPullUp, gpiod.WithBothEdges, gpiod.WithEventHandler(leftEventHandler), gpiod.WithDebounce(debouncingPeriod))
169	checkGPIOInitError(err)
170	defer l.Close()
171	r, err := gpiod.RequestLine("gpiochip0", rightButtonPinRef, gpiod.WithPullUp, gpiod.WithBothEdges, gpiod.WithEventHandler(rightEventHandler), gpiod.WithDebounce(debouncingPeriod))
172	checkGPIOInitError(err)
173	defer r.Close()
174	// Displays init
175	screendriver.InitializeDisplays()
176	// Renderer init
177	renderer.InitFrameBuffers()
178	// Boot screen show
179	ui.UIDisplayedMenu = 0
180	ui.RenderUI()
181	ui.UIConnectedToInternet = extras.PingCloudflare()
182	// Ping every 60s
183	for true {
184		time.Sleep(time.Minute)
185		ui.UIConnectedToInternet = extras.PingCloudflare()
186	}
187}