summaryrefslogtreecommitdiff
path: root/clockDisplay.go
diff options
context:
space:
mode:
Diffstat (limited to 'clockDisplay.go')
-rw-r--r--clockDisplay.go308
1 files changed, 308 insertions, 0 deletions
diff --git a/clockDisplay.go b/clockDisplay.go
new file mode 100644
index 0000000..cc20de3
--- /dev/null
+++ b/clockDisplay.go
@@ -0,0 +1,308 @@
+// Copyright 2022 Benjamin Barenblat
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+package main
+
+import (
+ "fmt"
+ "time"
+
+ "benjamin.barenblat.name/audiotrond/cfa635"
+)
+
+const (
+ lowerHalfSprite = iota
+ upperHalfSprite
+ lowerHalfEdgeSprite
+ upperHalfEdgeSprite
+ fullBlockSprite
+ fullBlockEdgeSprite
+ lowerRightSprite
+ rightLowerEdgeSprite
+)
+
+func initializeClockDisplay(lcd *cfa635.Module) error {
+ // Load sprites.
+
+ if err := lcd.SetCharacter(lowerHalfSprite, &[...]byte{
+ 0b00_000000,
+ 0b00_000000,
+ 0b00_000000,
+ 0b00_000000,
+ 0b00_000000,
+ 0b00_111111,
+ 0b00_111111,
+ 0b00_111111,
+ }); err != nil {
+ return err
+ }
+
+ if err := lcd.SetCharacter(upperHalfSprite, &[...]byte{
+ 0b00_111111,
+ 0b00_111111,
+ 0b00_111111,
+ 0b00_000000,
+ 0b00_000000,
+ 0b00_000000,
+ 0b00_000000,
+ 0b00_000000,
+ }); err != nil {
+ return err
+ }
+
+ if err := lcd.SetCharacter(lowerHalfEdgeSprite, &[...]byte{
+ 0b00_000000,
+ 0b00_000000,
+ 0b00_000000,
+ 0b00_000000,
+ 0b00_000000,
+ 0b00_001111,
+ 0b00_001111,
+ 0b00_001111,
+ }); err != nil {
+ return err
+ }
+
+ if err := lcd.SetCharacter(upperHalfEdgeSprite, &[...]byte{
+ 0b00_001111,
+ 0b00_001111,
+ 0b00_001111,
+ 0b00_000000,
+ 0b00_000000,
+ 0b00_000000,
+ 0b00_000000,
+ 0b00_000000,
+ }); err != nil {
+ return err
+ }
+
+ if err := lcd.SetCharacter(fullBlockSprite, &[...]byte{
+ 0b00_111111,
+ 0b00_111111,
+ 0b00_111111,
+ 0b00_111111,
+ 0b00_111111,
+ 0b00_111111,
+ 0b00_111111,
+ 0b00_111111,
+ }); err != nil {
+ return err
+ }
+
+ if err := lcd.SetCharacter(fullBlockEdgeSprite, &[...]byte{
+ 0b00_001111,
+ 0b00_001111,
+ 0b00_001111,
+ 0b00_001111,
+ 0b00_001111,
+ 0b00_001111,
+ 0b00_001111,
+ 0b00_001111,
+ }); err != nil {
+ return err
+ }
+
+ if err := lcd.SetCharacter(lowerRightSprite, &[...]byte{
+ 0b00_000001,
+ 0b00_000011,
+ 0b00_000111,
+ 0b00_001111,
+ 0b00_011111,
+ 0b00_111111,
+ 0b00_111111,
+ 0b00_111111,
+ }); err != nil {
+ return err
+ }
+
+ if err := lcd.SetCharacter(rightLowerEdgeSprite, &[...]byte{
+ 0b00_000001,
+ 0b00_000011,
+ 0b00_000111,
+ 0b00_001111,
+ 0b00_001111,
+ 0b00_001111,
+ 0b00_001111,
+ 0b00_001111,
+ }); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func blitClockDigit(n int, lcd *cfa635.LCDState, x int) {
+ switch n {
+ case 0:
+ lcd[0][x] = rightLowerEdgeSprite
+ lcd[0][x+1] = fullBlockSprite
+ lcd[0][x+2] = fullBlockSprite
+ lcd[1][x] = fullBlockEdgeSprite
+ lcd[1][x+2] = fullBlockSprite
+ lcd[2][x] = fullBlockEdgeSprite
+ lcd[2][x+2] = fullBlockSprite
+ lcd[3][x] = fullBlockEdgeSprite
+ lcd[3][x+1] = fullBlockSprite
+ lcd[3][x+2] = fullBlockSprite
+
+ case 1:
+ lcd[0][x+2] = lowerRightSprite
+ lcd[1][x+2] = fullBlockSprite
+ lcd[2][x+2] = fullBlockSprite
+ lcd[3][x+2] = fullBlockSprite
+
+ case 2:
+ lcd[0][x] = rightLowerEdgeSprite
+ lcd[0][x+1] = fullBlockSprite
+ lcd[0][x+2] = fullBlockSprite
+ lcd[1][x] = lowerHalfEdgeSprite
+ lcd[1][x+1] = lowerHalfSprite
+ lcd[1][x+2] = fullBlockSprite
+ lcd[2][x] = fullBlockEdgeSprite
+ lcd[2][x+1] = upperHalfSprite
+ lcd[2][x+2] = upperHalfSprite
+ lcd[3][x] = fullBlockEdgeSprite
+ lcd[3][x+1] = fullBlockSprite
+ lcd[3][x+2] = fullBlockSprite
+
+ case 3:
+ lcd[0][x] = rightLowerEdgeSprite
+ lcd[0][x+1] = fullBlockSprite
+ lcd[0][x+2] = fullBlockSprite
+ lcd[1][x] = lowerHalfEdgeSprite
+ lcd[1][x+1] = lowerHalfSprite
+ lcd[1][x+2] = fullBlockSprite
+ lcd[2][x] = upperHalfEdgeSprite
+ lcd[2][x+1] = upperHalfSprite
+ lcd[2][x+2] = fullBlockSprite
+ lcd[3][x] = fullBlockEdgeSprite
+ lcd[3][x+1] = fullBlockSprite
+ lcd[3][x+2] = fullBlockSprite
+
+ case 4:
+ lcd[0][x] = rightLowerEdgeSprite
+ lcd[0][x+2] = fullBlockSprite
+ lcd[1][x] = fullBlockEdgeSprite
+ lcd[1][x+1] = lowerHalfSprite
+ lcd[1][x+2] = fullBlockSprite
+ lcd[2][x] = upperHalfEdgeSprite
+ lcd[2][x+1] = upperHalfSprite
+ lcd[2][x+2] = fullBlockSprite
+ lcd[3][x+2] = fullBlockSprite
+
+ case 5:
+ lcd[0][x] = rightLowerEdgeSprite
+ lcd[0][x+1] = fullBlockSprite
+ lcd[0][x+2] = fullBlockSprite
+ lcd[1][x] = fullBlockEdgeSprite
+ lcd[1][x+1] = lowerHalfSprite
+ lcd[1][x+2] = lowerHalfSprite
+ lcd[2][x] = upperHalfEdgeSprite
+ lcd[2][x+1] = upperHalfSprite
+ lcd[2][x+2] = fullBlockSprite
+ lcd[3][x] = fullBlockEdgeSprite
+ lcd[3][x+1] = fullBlockSprite
+ lcd[3][x+2] = fullBlockSprite
+
+ case 6:
+ lcd[0][x] = rightLowerEdgeSprite
+ lcd[0][x+1] = fullBlockSprite
+ lcd[0][x+2] = fullBlockSprite
+ lcd[1][x] = fullBlockEdgeSprite
+ lcd[1][x+1] = lowerHalfSprite
+ lcd[1][x+2] = lowerHalfSprite
+ lcd[2][x] = fullBlockEdgeSprite
+ lcd[2][x+1] = upperHalfSprite
+ lcd[2][x+2] = fullBlockSprite
+ lcd[3][x] = fullBlockEdgeSprite
+ lcd[3][x+1] = fullBlockSprite
+ lcd[3][x+2] = fullBlockSprite
+
+ case 7:
+ lcd[0][x] = rightLowerEdgeSprite
+ lcd[0][x+1] = fullBlockSprite
+ lcd[0][x+2] = fullBlockSprite
+ lcd[1][x+2] = fullBlockSprite
+ lcd[2][x+2] = fullBlockSprite
+ lcd[3][x+2] = fullBlockSprite
+
+ case 8:
+ lcd[0][x] = rightLowerEdgeSprite
+ lcd[0][x+1] = fullBlockSprite
+ lcd[0][x+2] = fullBlockSprite
+ lcd[1][x] = fullBlockEdgeSprite
+ lcd[1][x+1] = lowerHalfSprite
+ lcd[1][x+2] = fullBlockSprite
+ lcd[2][x] = fullBlockEdgeSprite
+ lcd[2][x+1] = upperHalfSprite
+ lcd[2][x+2] = fullBlockSprite
+ lcd[3][x] = fullBlockEdgeSprite
+ lcd[3][x+1] = fullBlockSprite
+ lcd[3][x+2] = fullBlockSprite
+
+ case 9:
+ lcd[0][x] = rightLowerEdgeSprite
+ lcd[0][x+1] = fullBlockSprite
+ lcd[0][x+2] = fullBlockSprite
+ lcd[1][x] = fullBlockEdgeSprite
+ lcd[1][x+1] = lowerHalfSprite
+ lcd[1][x+2] = fullBlockSprite
+ lcd[2][x] = upperHalfEdgeSprite
+ lcd[2][x+1] = upperHalfSprite
+ lcd[2][x+2] = fullBlockSprite
+ lcd[3][x+2] = fullBlockSprite
+
+ default:
+ panic(fmt.Sprint("unknown digit ", n))
+ }
+}
+
+func clockView(now time.Time) *view {
+ var new view
+ new.LCD = cfa635.ClearedLCDState()
+
+ now = now.Local()
+ h := now.Hour() % 12
+ if h == 0 {
+ h = 12
+ }
+ if h >= 10 {
+ blitClockDigit(1, new.LCD, -2)
+ h -= 10
+ }
+ blitClockDigit(h, new.LCD, 1)
+
+ new.LCD[1][4] = 0xbb
+ new.LCD[2][4] = 0xbb
+
+ m := now.Minute()
+ blitClockDigit(m/10, new.LCD, 5)
+ blitClockDigit(m%10, new.LCD, 8)
+
+ new.LCD[1][11] = 0xbb
+ new.LCD[2][11] = 0xbb
+
+ s := now.Second()
+ blitClockDigit(s/10, new.LCD, 12)
+ blitClockDigit(s%10, new.LCD, 15)
+
+ if now.Hour() < 12 {
+ new.LCD[2][19] = 'a'
+ } else {
+ new.LCD[2][19] = 'p'
+ }
+ new.LCD[3][19] = 'm'
+
+ return &new
+}