1package main
  2
  3import (
  4	"fmt"
  5	"log"
  6	"syscall"
  7	"time"
  8
  9	"tokei.pi/extras"
 10	"tokei.pi/renderer"
 11	"tokei.pi/screendriver"
 12	"tokei.pi/screenfader"
 13	"tokei.pi/ui"
 14	"tokei.pi/weather"
 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
 35/*
 36func checkIfBothButtonsArePressed(currentButton string) bool {
 37	if extras.LeftButtonState == true {
 38		if extras.RightButtonState == true {
 39			fmt.Println("Both buttons pressed!")
 40			ui.UISelectionIndex = ui.UISelectionIndexBuffer
 41			if ui.UIDisplayedMenu == 1 {
 42				selectBook()
 43				fmt.Println("Loaded a book!")
 44				return true
 45			} else if ui.UIDisplayedMenu == 2 {
 46				appdata.SaveBookData(phnparser.LoadedBookHash, ui.UISelectionIndex)
 47				ui.RenderUI()
 48				fmt.Println("Saved the position!")
 49				return true
 50			}
 51		}
 52	}
 53	return false
 54}*/
 55
 56func leftEventHandler(evt gpiod.LineEvent) {
 57	edge := "rising"
 58	extras.LeftButtonState = false
 59	if evt.Type == gpiod.LineEventFallingEdge {
 60		edge = "falling"
 61		extras.LeftButtonState = true
 62		extras.LeftButtonPressedTime = time.Now()
 63	}
 64	if edge == "rising" {
 65		if time.Now().Sub(extras.LeftButtonPressedTime).Seconds() >= extras.NavigationHoldDuration {
 66			fmt.Println("Back nav placeholder")
 67		}
 68	}
 69	if edge == "falling" {
 70		/*
 71			if checkIfBothButtonsArePressed("left") {
 72				return
 73			}*/
 74		fmt.Println("Left button pressed!")
 75		screenfader.ClickRegistered()
 76		ui.UIDisplayedMenu--
 77		if ui.UIDisplayedMenu < 1 {
 78			ui.UIDisplayedMenu = ui.UIWidgetCount
 79		}
 80		ui.UITopBarTitle = fmt.Sprintf("Widget set %d", ui.UIDisplayedMenu)
 81		ui.RenderUI()
 82	}
 83}
 84
 85func rightEventHandler(evt gpiod.LineEvent) {
 86	edge := "rising"
 87	extras.RightButtonState = false
 88	if evt.Type == gpiod.LineEventFallingEdge {
 89		edge = "falling"
 90		extras.RightButtonState = true
 91	}
 92	if edge == "falling" {
 93		/*
 94			if checkIfBothButtonsArePressed("right") {
 95				return
 96			}*/
 97		fmt.Println("Right button pressed!")
 98		screenfader.ClickRegistered()
 99		ui.UIDisplayedMenu++
100		if ui.UIDisplayedMenu > ui.UIWidgetCount {
101			ui.UIDisplayedMenu = 1
102		}
103		ui.UITopBarTitle = fmt.Sprintf("Widget set %d", ui.UIDisplayedMenu)
104		ui.RenderUI()
105	}
106}
107
108func UIMainloop() {
109	for true {
110		// Rerender UI every second
111		time.Sleep(time.Second)
112		ui.RenderUI()
113	}
114}
115
116func UIWeatherMainloop() {
117	for true {
118		weather.UpdateCurrentWeather()
119		time.Sleep(240 * time.Second)
120	}
121}
122
123func ScreenFaderMainloop() {
124	for true {
125		screenfader.AdaptDisplayBrightness()
126		timeSinceLastClick := int(time.Now().UnixMilli() - screenfader.LastClickTimestamp)
127		if timeSinceLastClick < screenfader.ScreenFadeDelay*1000 {
128			time.Sleep(100 * time.Millisecond)
129		} else if timeSinceLastClick < screenfader.ScreenFadeDelay*1000+screenfader.ScreenFadeDuration*1000 {
130			time.Sleep(17 * time.Millisecond)
131		} else {
132			time.Sleep(1000 * time.Millisecond)
133		}
134	}
135}
136
137func main() {
138	// Config
139	// Input
140	leftButtonPinRef := rpi.J8p11
141	rightButtonPinRef := rpi.J8p13
142	debouncingPeriod := 10 * time.Millisecond
143	extras.NavigationHoldDuration = 3
144	// Screen
145	renderer.ScreenCount = 2
146	renderer.ScreenWidth = 128
147	renderer.ScreenHeight = 64
148	// UI
149	ui.BuildVersion = "V2022.07.11"
150	ui.UIMargin = 1
151	ui.UITopBarHeight = 10
152	ui.UILineHeight = 8
153	ui.UIFontHorizontalSpacing = 9
154	ui.UIMaxBookLines = 6
155	ui.UIWidgetCount = 4
156	// Display Driver
157	screendriver.I2CBuses = []string{"1", "4"}
158	// Extras
159	extras.CloudflareIP = "1.1.1.1"
160	// Weather
161	weather.OpenWeatherMapAPIKey = "2ee79601c807b825fa622addcb4d9b57"
162	weather.CityOfObservation = "Paris, FR"
163	weather.Latitude = 48.834590
164	weather.Longitude = 2.398260
165	// Code
166	// GPIO init
167	l, err := gpiod.RequestLine("gpiochip0", leftButtonPinRef, gpiod.WithPullUp, gpiod.WithBothEdges, gpiod.WithEventHandler(leftEventHandler), gpiod.WithDebounce(debouncingPeriod))
168	checkGPIOInitError(err)
169	defer l.Close()
170	r, err := gpiod.RequestLine("gpiochip0", rightButtonPinRef, gpiod.WithPullUp, gpiod.WithBothEdges, gpiod.WithEventHandler(rightEventHandler), gpiod.WithDebounce(debouncingPeriod))
171	checkGPIOInitError(err)
172	defer r.Close()
173	// Displays init
174	screendriver.InitializeDisplays()
175	// Renderer init
176	renderer.InitFrameBuffers()
177	// Boot screen show
178	ui.UIDisplayedMenu = 0
179	ui.RenderUI()
180	ui.UIConnectedToInternet = extras.PingCloudflare()
181	go UIMainloop()
182	go UIWeatherMainloop()
183	go ScreenFaderMainloop()
184	// Ping every 60s
185	for true {
186		time.Sleep(time.Minute)
187		ui.UIConnectedToInternet = extras.PingCloudflare()
188	}
189
190}