5
5
6
6
import machine , micropython , json , time , _thread , network , os
7
7
import Logger
8
- import st7789 , axp202 , axp202_constants , ft6x36 , pcf8563 , bma423
8
+ import st7789 , axp202 , axp202_constants , ft6x36 , pcf8563 , bma423 , adafruit_drv2605
9
9
import TextMode
10
10
import Events
11
11
import esp , esp32
12
12
import Single
13
13
14
+ WATCHV1 = int (0 )
15
+ WATCHV2 = int (1 )
16
+ WATCHV3 = int (2 )
17
+ WATCHS3 = int (3 )
18
+
14
19
# Remember to write irq handlers for SPEED, we have SO MUCH RAM
15
20
# also everything that has to do with hardware probably should be lbyl
16
21
@@ -23,23 +28,16 @@ class Hardware:
23
28
24
29
def identify_version (self ):
25
30
try :
26
- self .pmu .disablePower (axp202_constants .AXP202_LDO3 )
27
- touch = ft6x36 .FT6x36 (machine .SoftI2C (scl = machine .Pin (32 , machine .Pin .OUT ), sda = machine .Pin (23 , machine .Pin .OUT ), freq = 100000 ))
28
- touch .power_mode = 0
29
- return 0 #V1
31
+ drv_i2c = machine .SoftI2C (scl = machine .Pin (22 , machine .Pin .OUT ), sda = machine .Pin (21 , machine .Pin .OUT ), freq = 100000 )
32
+ vibration_controller = adafruit_drv2605 .DRV2605 (drv_i2c )
30
33
except OSError :
31
- pass
32
- self .pmu .setLDO3Voltage (3300 )
33
- self .pmu .enablePower (axp202_constants .AXP202_LDO3 )
34
- self .pmu .disablePower (axp202_constants .AXP202_EXTEN ); # reset touch
35
- time .sleep_ms (10 )
36
- self .pmu .enablePower (axp202_constants .AXP202_EXTEN );
37
- touch = ft6x36 .FT6x36 (machine .SoftI2C (scl = machine .Pin (32 , machine .Pin .OUT ), sda = machine .Pin (23 , machine .Pin .OUT ), freq = 100000 ))
38
- touch .power_mode = 0
39
- return 1 #V2
34
+ return WATCHV1
35
+ if "S3" in os .uname ()[4 ]:
36
+ return WATCHS3 #S3
37
+ return WATCHV2 #V2
40
38
41
39
def init_ft6336 (self ):
42
- if self .WatchVersion == 1 :
40
+ if self .WatchVersion == WATCHV2 :
43
41
self .pmu .disablePower (axp202_constants .AXP202_EXTEN ); # reset touch
44
42
time .sleep_ms (15 )
45
43
self .pmu .enablePower (axp202_constants .AXP202_EXTEN );
@@ -63,36 +61,37 @@ def init_st7789(self):
63
61
# shameful display of 3 wire SPI and slow updates
64
62
# why not 2-line or 4-line SPI lilygo?
65
63
# also uses wrong MOSI pin, slowing it down even more, fixed on TWATCH S3
66
- cs = machine . Pin ( 5 , machine . Pin . OUT )
67
- dc = machine .Pin (27 , machine .Pin .OUT )
68
- if self . WatchVersion == 1 :
64
+ if self . WatchVersion == WATCHV2 :
65
+ cs = machine .Pin (5 , machine .Pin .OUT )
66
+ dc = machine . Pin ( 27 , machine . Pin . OUT )
69
67
display_spi = machine .SPI (1 ,baudrate = 40000000 ,sck = machine .Pin (18 , machine .Pin .OUT ),mosi = machine .Pin (19 , machine .Pin .OUT )) # will only work with modded MPY to add flag for dummy bit, otherwise use baudrate 27000000, ESP32 limit is 80Mhz
70
68
self .display = st7789 .ST7789 (display_spi , Hardware .DISPLAY_WIDTH , Hardware .DISPLAY_HEIGHT , cs = cs , dc = dc , backlight = machine .Pin (25 , machine .Pin .OUT ), rotation = 2 , buffer_size = Hardware .DISPLAY_WIDTH * Hardware .DISPLAY_HEIGHT * 2 ,)
69
+ elif self .WatchVersion == WATCHS3 :
70
+ cs = machine .Pin (12 , machine .Pin .OUT )
71
+ dc = machine .Pin (38 , machine .Pin .OUT )
72
+ display_spi = machine .SPI (0 ,baudrate = 80000000 ,sck = machine .Pin (18 , machine .Pin .OUT ),mosi = machine .Pin (13 , machine .Pin .OUT )) # will only work with modded MPY to add flag for dummy bit, otherwise use baudrate 27000000, ESP32 limit is 80Mhz
73
+ self .display = st7789 .ST7789 (display_spi , Hardware .DISPLAY_WIDTH , Hardware .DISPLAY_HEIGHT , cs = cs , dc = dc , backlight = machine .Pin (45 , machine .Pin .OUT ), rotation = 2 , buffer_size = Hardware .DISPLAY_WIDTH * Hardware .DISPLAY_HEIGHT * 2 ,)
71
74
else :
75
+ cs = machine .Pin (5 , machine .Pin .OUT )
76
+ dc = machine .Pin (27 , machine .Pin .OUT )
72
77
display_spi = machine .SPI (1 ,baudrate = 80000000 ,sck = machine .Pin (18 , machine .Pin .OUT ),mosi = machine .Pin (19 , machine .Pin .OUT )) # will only work with modded MPY to add flag for dummy bit, otherwise use baudrate 27000000, ESP32 limit is 80Mhz
73
78
self .display = st7789 .ST7789 (display_spi , Hardware .DISPLAY_WIDTH , Hardware .DISPLAY_HEIGHT , cs = cs , dc = dc , backlight = machine .Pin (12 , machine .Pin .OUT ), rotation = 2 , buffer_size = Hardware .DISPLAY_WIDTH * Hardware .DISPLAY_HEIGHT * 2 ,)
74
79
self .display .init ()
75
80
self .display .on ()
76
81
#self.display.fill(st7789.BLACK)
82
+ Logger .log ("Hi! Display initialized." )
77
83
78
- def __init__ (self ):
79
- self .WatchVersion = 0 # V1
80
- self .hardware = []
84
+ def init_axp202 (self ):
85
+ Logger .log ("Initializing AXP202 PMU..." )
81
86
sObject = Single .Settings .getSettingObject (Single .Settings .hardware )
82
87
if sObject == None :
83
88
sObject = {}
84
- Logger .log ("Initializing Hardware..." )
85
- machine .freq (240000000 )
86
-
87
-
88
- Logger .log ("Initializing AXP202 PMU..." )
89
- # BackLight Poweif fb[i*2*DISPLAY_HEIGHT + j*2] > 0 or fb[i*2*DISPLAY_HEIGHT + j*2 + 1] > 0:r
90
89
self .pmu = axp202 .PMU ()
91
- self .pmu .enablePower (axp202 .AXP202_LDO2 )
92
90
if sObject .get ("BacklightVoltage" ) != None :
93
91
self .pmu .setLDO2Voltage (sObject ["BacklightVoltage" ])
94
92
else :
95
93
self .pmu .setLDO2Voltage (2800 ) #default backlight level todo: load from settings (or load it from app 0)
94
+ self .pmu .enablePower (axp202_constants .AXP202_LDO2 )
96
95
self .pmu .setDC3Voltage (Hardware .Vc3V3 )
97
96
'''very low 3.3v rail to minimize power consumption,
98
97
esp can go down to 2.3v (and might be fine down to 1.8v too)
@@ -105,7 +104,8 @@ def __init__(self):
105
104
mic: 1.6v
106
105
psram: 2.7v :(
107
106
'''
108
- self .pmu .disablePower (axp202_constants .AXP202_LDO3 ) # on V2, Touch+ TFT
107
+ if self .WatchVersion != WATCHV2 :
108
+ self .pmu .disablePower (axp202_constants .AXP202_LDO3 ) # on V2, Touch+ TFT
109
109
self .pmu .disablePower (axp202_constants .AXP202_LDO4 ) # on V2, GPS
110
110
self .pmu .disablePower (axp202_constants .AXP202_DCDC2 )
111
111
self .pmu .clearIRQ ()
@@ -121,23 +121,60 @@ def __init__(self):
121
121
#self.pmu.setlongPressTime(axp202_constants.AXP_LONGPRESS_TIME_2S)
122
122
#self.pmu.setTimeOutShutdown(True)
123
123
#self.pmu.enableIRQ(axp202_constants.AXP202_ALL_IRQ)
124
-
125
124
self .pmu .setChargingTargetVoltage (axp202_constants .AXP202_TARGET_VOL_4_2V ) # sane voltage values for battery management
125
+ if self .WatchVersion == WATCHV2 :
126
+ self .pmu .setLDO3Voltage (3300 )
127
+ self .pmu .enablePower (axp202_constants .AXP202_LDO3 )
128
+ self .pmu .write_byte (axp202_constants .AXP202_GPIO0_CTL , 1 ) # everything to 0 except first byte, enable GPIO as high so it desinhibit DRV2605... why was this necessary, and only on V2 ?
129
+
130
+ def init_irq (self ):
131
+ pin38 = machine .Pin (38 , machine .Pin .IN ) #irq touch
132
+ pin37 = machine .Pin (37 , machine .Pin .IN ) #irq external rtc
133
+ pin39 = machine .Pin (39 , machine .Pin .IN ) #irq IMU
134
+ pin35 = machine .Pin (35 , machine .Pin .IN ) #irq axp202
135
+ #esp32.wake_on_ext1((pin35, pin39, pin38, pin37), esp32.WAKEUP_ANY_HIGH)
136
+ #esp32.wake_on_ext0(pin35, esp32.WAKEUP_ALL_LOW)
137
+ pin35 .irq (self .irq_pmu , trigger = machine .Pin .IRQ_FALLING , wake = machine .DEEPSLEEP | machine .SLEEP )
138
+ pin38 .irq (self .irq_touch , trigger = machine .Pin .IRQ_RISING )
139
+ pin39 .irq (self .irq_imu , trigger = machine .Pin .IRQ_RISING , wake = machine .DEEPSLEEP | machine .SLEEP )
140
+ #print("pin 39 is", pin39.value())
141
+
142
+ self .irq_touch_buffer_pos1 = bytearray (4 ) #pre-allocation
143
+ self .irq_touch_buffer_pos2 = bytearray (4 )
144
+ self .irq_touch_present = False
145
+ #self.irq_touch_time = 0
146
+ #self.irq_touch_fired_release = True
147
+
148
+ def init_irq_s3 (self ):
149
+ pin16 = machine .Pin (16 , machine .Pin .IN ) #irq touch
150
+ pin17 = machine .Pin (17 , machine .Pin .IN ) #irq external rtc
151
+ pin14 = machine .Pin (14 , machine .Pin .IN ) #irq IMU
152
+ pin21 = machine .Pin (21 , machine .Pin .IN ) #irq axp2101
153
+ pin21 .irq (self .irq_pmu , trigger = machine .Pin .IRQ_FALLING , wake = machine .DEEPSLEEP | machine .SLEEP )
154
+ pin16 .irq (self .irq_touch , trigger = machine .Pin .IRQ_RISING )
155
+ pin14 .irq (self .irq_imu , trigger = machine .Pin .IRQ_RISING , wake = machine .DEEPSLEEP | machine .SLEEP )
156
+
157
+ self .irq_touch_buffer_pos1 = bytearray (4 ) #pre-allocation
158
+ self .irq_touch_buffer_pos2 = bytearray (4 )
159
+ self .irq_touch_present = False
160
+
161
+ def __init__ (self ):
162
+ self .WatchVersion = 0 # V1
163
+ self .hardware = []
164
+ Logger .log ("Initializing Hardware..." )
165
+ machine .freq (240000000 )
126
166
127
167
self .WatchVersion = self .identify_version ()
128
168
self .display_lock = _thread .allocate_lock () # for locking render while we sleep, notably on V2 watch where we need to re-initialize at wake up
129
169
self .display_lock .acquire ()
130
-
131
- if self .WatchVersion == 1 :
132
- self .pmu .setLDO3Voltage (3300 )
133
- self .pmu .enablePower (axp202_constants .AXP202_LDO3 )
134
- time .sleep_ms (10 )
135
-
136
- Logger .log ("Initializing firmware pre-init graphics." )
170
+ if self .WatchVersion < WATCHS3 :
171
+ self .init_axp202 ()
172
+ time .sleep_ms (20 )
173
+ else :
174
+ self .init_axp2101 ()
137
175
138
176
self .init_st7789 ()
139
177
140
- Logger .log ("Hi! Display initialized." )
141
178
Logger .log ("CPU frequ: " + str (machine .freq ()))
142
179
Logger .log ("Flash Size: " + str (esp .flash_size ()))
143
180
Logger .log ("Unique ID: " + str (int .from_bytes (machine .unique_id (), 'big' , False )))
@@ -204,29 +241,21 @@ def __init__(self):
204
241
205
242
self .gesture_startpos = (0 ,0 ) # gesture emulation
206
243
207
- pin38 = machine .Pin (38 , machine .Pin .IN ) #irq touch
208
- pin37 = machine .Pin (37 , machine .Pin .IN ) #irq external rtc
209
- pin39 = machine .Pin (39 , machine .Pin .IN ) #irq IMU
210
- pin35 = machine .Pin (35 , machine .Pin .IN ) #irq axp202
211
- #esp32.wake_on_ext1((pin35, pin39, pin38, pin37), esp32.WAKEUP_ANY_HIGH)
212
- #esp32.wake_on_ext0(pin35, esp32.WAKEUP_ALL_LOW)
213
- pin35 .irq (self .irq_pmu , trigger = machine .Pin .IRQ_FALLING , wake = machine .DEEPSLEEP | machine .SLEEP )
214
- pin38 .irq (self .irq_touch , trigger = machine .Pin .IRQ_RISING )
215
- pin39 .irq (self .irq_imu , trigger = machine .Pin .IRQ_RISING , wake = machine .DEEPSLEEP | machine .SLEEP )
216
- #print("pin 39 is", pin39.value())
217
-
218
- self .irq_touch_buffer_pos1 = bytearray (4 ) #pre-allocation
219
- self .irq_touch_buffer_pos2 = bytearray (4 )
220
- self .irq_touch_present = False
221
- #self.irq_touch_time = 0
222
- #self.irq_touch_fired_release = True
244
+ if self .WatchVersion < WATCHS3 :
245
+ self .init_irq ()
246
+ else :
247
+ self .init_irq_s3 ()
223
248
224
- #self.oldfb = bytearray(DISPLAY_WIDTH * DISPLAY_HEIGHT * 2)
225
249
226
250
self .wifi_lock = _thread .allocate_lock ()
227
251
self .wifi = None
228
252
229
- self .vibrator = machine .Pin (4 , machine .Pin .OUT )
253
+ if self .WatchVersion == WATCHV1 or self .WatchVersion == WATCHV3 :
254
+ self .vibrator = machine .Pin (4 , machine .Pin .OUT )
255
+ else :
256
+ self .vibration_controller = adafruit_drv2605 .DRV2605 (sensor_i2c )
257
+ self .vibration_controller .mode = adafruit_drv2605 .MODE_REALTIME # i really cant be bothered lol drv looks like it has nice functions but i have other priorities rn
258
+ self .vibrator = None
230
259
231
260
machine .freq (80000000 ) #todo: set to user value (give a slider with choice between 240, 160, and 80 mhz?)
232
261
self .display_lock .release ()
@@ -263,7 +292,8 @@ def lightsleep(self, time_ms, force = False, callback = None):
263
292
self .display .off ()
264
293
self .display .sleep_mode (True )
265
294
self .pmu .disablePower (axp202_constants .AXP202_LDO2 )
266
- self .pmu .disablePower (axp202_constants .AXP202_LDO3 ) # shutdown full LCD in case of V2 watch
295
+ if self .WatchVersion == WATCHV2 :
296
+ self .pmu .disablePower (axp202_constants .AXP202_LDO3 ) # shutdown full LCD in case of V2 watch
267
297
self .pmu .disablePower (axp202_constants .AXP202_LDO4 )
268
298
self .pmu .disablePower (axp202_constants .AXP202_DCDC2 )
269
299
self .pmu .clearIRQ ()
@@ -275,19 +305,19 @@ def lightsleep(self, time_ms, force = False, callback = None):
275
305
# monitor mode low rate of update good workaround?
276
306
should_sleep = True
277
307
while should_sleep :
278
- if self .WatchVersion == 0 :
308
+ if self .WatchVersion == WATCHV1 :
279
309
self .touch .monitor_period = 254 # low refresh? Seems to work (datasheet says 25 time a second and default value is 40, i suppose that's milliseconds)
280
310
self .touch .power_mode = 1
281
311
machine .lightsleep (time_ms )
282
312
if callback != None :
283
313
should_sleep = callback ()
284
314
else :
285
315
should_sleep = False
286
- if self .WatchVersion == 0 :
316
+ if self .WatchVersion == WATCHV1 :
287
317
self .touch .power_mode = 0
288
318
self .pmu .setDC3Voltage (Hardware .Vc3V3 )
289
319
self .pmu .enablePower (axp202_constants .AXP202_LDO2 )
290
- if self .WatchVersion == 1 :
320
+ if self .WatchVersion == WATCHV2 :
291
321
self .pmu .setLDO3Voltage (3300 )
292
322
self .pmu .enablePower (axp202_constants .AXP202_LDO3 )
293
323
time .sleep_ms (20 ) # wait for potaaytoes to be warmed up
@@ -304,15 +334,24 @@ def blit_buffer_rgb565(self, array):
304
334
# seems like to get more speed would need to do quite a lot on the C side of things
305
335
306
336
def feedback1 (self ):
307
- self .vibrator .on ()
337
+ if self .vibrator :
338
+ self .vibrator .on ()
339
+ elif self .vibration_controller :
340
+ self .vibration_controller .realtime_value = 127
308
341
machine .Timer (3 , mode = machine .Timer .ONE_SHOT , period = 20 , callback = self .feedback_frame )
309
342
310
343
def feedback2 (self ):
311
- self .vibrator .on ()
344
+ if self .vibrator :
345
+ self .vibrator .on ()
346
+ elif self .vibration_controller :
347
+ self .vibration_controller .realtime_value = 127
312
348
machine .Timer (3 , mode = machine .Timer .ONE_SHOT , period = 50 , callback = self .feedback_frame )
313
349
314
350
def feedback_frame (self , _ ):
315
- self .vibrator .off ()
351
+ if self .vibrator :
352
+ self .vibrator .off ()
353
+ elif self .vibration_controller :
354
+ self .vibration_controller .realtime_value = 0
316
355
317
356
def sync_ntp (self ):
318
357
try :
@@ -386,7 +425,7 @@ def irq_touch(self, pin):
386
425
#self.irq_touch_fired_release = False
387
426
self .irq_touch_time = time .ticks_ms ()
388
427
except OSError as e :
389
- if self .WatchVersion != 1 : # that's a possibility on V2 because we cant check lock in irq without causing issues so we do EAFP, since it's only a problem when going to sleep
428
+ if self .WatchVersion != WATCHV2 : # that's a possibility on V2 because we cant check lock in irq without causing issues so we do EAFP, since it's only a problem when going to sleep
390
429
print (e )
391
430
except Exception as e :
392
431
print ("we shaint be there... And it's not okay, you might need to reboot(touch irq)" )
0 commit comments