-
Notifications
You must be signed in to change notification settings - Fork 1
/
code.py
executable file
·155 lines (134 loc) · 4.68 KB
/
code.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
"""
Zwiftendo is a bluetooth keyboard for controlling zwift and music
"""
# import libs
import board
import busio
from analogio import AnalogIn
from micropython import const
from adafruit_seesaw.seesaw import Seesaw
from adafruit_debouncer import Debouncer
from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS
from adafruit_hid.consumer_control import ConsumerControl
from adafruit_hid.consumer_control_code import ConsumerControlCode
from adafruit_hid.keycode import Keycode
import adafruit_ble
from adafruit_ble.advertising import Advertisement
from adafruit_ble.advertising.standard import ProvideServicesAdvertisement
from adafruit_ble.services.standard.hid import HIDService
from adafruit_ble.services.standard.device_info import DeviceInfoService
from adafruit_ble.services.standard import BatteryService
# Define buttons to pin mapping
BUTTON_A = const(6)
BUTTON_B = const(7)
BUTTON_Y = const(9)
BUTTON_X = const(10)
BUTTON_SEL = const(14)
# Setup battery voltage level ADC pin
vbat_voltage = AnalogIn(board.VOLTAGE_MONITOR)
# Setup our i2c but to the Joy Feather
i2c_bus = busio.I2C(board.SCL, board.SDA)
ss = Seesaw(i2c_bus)
# Use default HID descriptor
hid = HIDService()
bat = BatteryService()
# device_info seems to throw an error on circuitpython v6.1.0+beta2
# device_info = DeviceInfoService(
# software_revision=adafruit_ble.__version__, manufacturer="Adafruit Industries"
# )
advertisement = ProvideServicesAdvertisement(hid)
advertisement.appearance = 961
scan_response = Advertisement()
ble = adafruit_ble.BLERadio()
ble.name = "Zwiftendo"
# Teardown any other BLE connections
if ble.connected:
for c in ble.connections:
c.disconnect()
# Start advertising on BLE
print("Advertising...")
ble.start_advertising(advertisement, scan_response)
# Setup bluetooth HID resources
consumer_control = ConsumerControl(hid.devices)
k = Keyboard(hid.devices)
kl = KeyboardLayoutUS(k)
def make_pin_reader(pin):
""" Creates a pin reader to feed to Debouncer """
ss.pin_mode(pin, ss.INPUT_PULLUP)
return lambda: ss.digital_read(pin)
def get_bat_percent(pin):
# percentage relative to 4.2V max
return (((pin.value * 3.3) / 65536 * 2)/4.2)*100
# Create debounced button inputs
btnA = Debouncer(make_pin_reader(BUTTON_A))
btnB = Debouncer(make_pin_reader(BUTTON_B))
btnX = Debouncer(make_pin_reader(BUTTON_X))
btnY = Debouncer(make_pin_reader(BUTTON_Y))
btnSel = Debouncer(make_pin_reader(BUTTON_SEL))
def read_joy_stick():
""" Read the joystick and send UP,DOWN,LEFT,RIGHT commands"""
x = ss.analog_read(2)
y = ss.analog_read(3)
if y > 1000:
if ble.connected: k.send(Keycode.RIGHT_ARROW)
print("RIGHT")
if y < 30:
if ble.connected: k.send(Keycode.LEFT_ARROW)
print("LEFT")
if x > 1000:
if ble.connected: k.send(Keycode.DOWN_ARROW)
print("DOWN")
if x < 30:
if ble.connected: k.send(Keycode.UP_ARROW)
print("UP")
def read_buttons():
""" Scan the buttons on falling edge and send commands """
btnA.update()
btnB.update()
btnX.update()
btnY.update()
btnSel.update()
if btnA.fell:
# Send ENTER/RETURN if BLE connected
if ble.connected: k.send(Keycode.ENTER)
print('A Fell')
if btnB.fell:
# Skip to next track on media if connected via BLE
if ble.connected: consumer_control.send(ConsumerControlCode.SCAN_NEXT_TRACK)
print('B Fell')
if btnX.fell:
# TODO: allow this to be toggled for race or training mode
# Press TAB to skip workout block
if ble.connected: k.send(Keycode.TAB)
print('X Fell')
if btnY.fell:
# Play or Pause current media
consumer_control.send(ConsumerControlCode.PLAY_PAUSE)
print('Y Fell')
if btnSel.fell:
# If we get a start, trigger applescript on laptop with key combo `ctrl`+`shift`+`=`.
if ble.connected: k.send(Keycode.CONTROL, Keycode.SHIFT, Keycode.EQUALS)
print('Select Fell')
def update_battery_state():
""" Update the battery level status """
# Check battery level
bat_level = get_bat_percent(vbat_voltage)
print("Battery Level: ", bat_level)
# Update bluetooth battery level prop
bat.level = int(bat_level)
def check_ble_connection():
print("check BLE")
if not ble.connected and not ble.advertising:
# Start advertising on BLE
print("Disconnected going back to advertising...")
ble.start_advertising(advertisement, scan_response)
loop_count = 0
while True:
read_joy_stick()
read_buttons()
loop_count = loop_count + 1
if loop_count > 1000:
update_battery_state()
loop_count = 0
check_ble_connection()