@@ -19,6 +19,8 @@ class ArduinoAlvik:
1919
2020 _update_thread_running = False
2121 _update_thread_id = None
22+ _touch_events_thread_running = False
23+ _touch_events_thread_id = None
2224
2325 def __new__ (cls ):
2426 if not hasattr (cls , '_instance' ):
@@ -68,6 +70,7 @@ def __init__(self):
6870 self ._angular_velocity = None
6971 self ._last_ack = ''
7072 self ._version = [None , None , None ]
73+ self ._touch_events = _ArduinoAlvikTouchEvents ()
7174
7275 @staticmethod
7376 def is_on () -> bool :
@@ -135,7 +138,7 @@ def _idle(self, delay_=1, check_on_thread=False) -> None:
135138 sys .exit ()
136139 except Exception as e :
137140 pass
138- #print(f'Unable to read SOC: {e}')
141+ # print(f'Unable to read SOC: {e}')
139142 finally :
140143 LEDR .value (1 )
141144 LEDG .value (1 )
@@ -179,6 +182,9 @@ def begin(self) -> int:
179182 self ._idle (1000 )
180183 self ._begin_update_thread ()
181184 sleep_ms (100 )
185+ if self ._touch_events .has_callbacks ():
186+ print ('Starting touch events' )
187+ self ._start_touch_events_thread ()
182188 self ._reset_hw ()
183189 self ._flush_uart ()
184190 self ._snake_robot (1000 )
@@ -293,9 +299,12 @@ def stop(self):
293299 # turn off UI leds
294300 self ._set_leds (0x00 )
295301
296- # stop the update thrad
302+ # stop the update thread
297303 self ._stop_update_thread ()
298304
305+ # stop touch events thread
306+ self ._stop_touch_events_thread ()
307+
299308 # delete _instance
300309 del self .__class__ ._instance
301310 gc .collect ()
@@ -953,6 +962,99 @@ def print_status(self):
953962 continue
954963 print (f'{ str (a ).upper ()} = { getattr (self , str (a ))} ' )
955964
965+ def on_touch_ok_pressed (self , callback : callable , args : tuple = ()) -> None :
966+ """
967+ Register callback when touch button OK is pressed
968+ :param callback:
969+ :param args:
970+ :return:
971+ """
972+ self ._touch_events .register_callback ('on_ok_pressed' , callback , args )
973+
974+ def on_touch_cancel_pressed (self , callback : callable , args : tuple = ()) -> None :
975+ """
976+ Register callback when touch button CANCEL is pressed
977+ :param callback:
978+ :param args:
979+ :return:
980+ """
981+ self ._touch_events .register_callback ('on_cancel_pressed' , callback , args )
982+
983+ def on_touch_center_pressed (self , callback : callable , args : tuple = ()) -> None :
984+ """
985+ Register callback when touch button CENTER is pressed
986+ :param callback:
987+ :param args:
988+ :return:
989+ """
990+ self ._touch_events .register_callback ('on_center_pressed' , callback , args )
991+
992+ def on_touch_up_pressed (self , callback : callable , args : tuple = ()) -> None :
993+ """
994+ Register callback when touch button UP is pressed
995+ :param callback:
996+ :param args:
997+ :return:
998+ """
999+ self ._touch_events .register_callback ('on_up_pressed' , callback , args )
1000+
1001+ def on_touch_left_pressed (self , callback : callable , args : tuple = ()) -> None :
1002+ """
1003+ Register callback when touch button LEFT is pressed
1004+ :param callback:
1005+ :param args:
1006+ :return:
1007+ """
1008+ self ._touch_events .register_callback ('on_left_pressed' , callback , args )
1009+
1010+ def on_touch_down_pressed (self , callback : callable , args : tuple = ()) -> None :
1011+ """
1012+ Register callback when touch button DOWN is pressed
1013+ :param callback:
1014+ :param args:
1015+ :return:
1016+ """
1017+ self ._touch_events .register_callback ('on_down_pressed' , callback , args )
1018+
1019+ def on_touch_right_pressed (self , callback : callable , args : tuple = ()) -> None :
1020+ """
1021+ Register callback when touch button RIGHT is pressed
1022+ :param callback:
1023+ :param args:
1024+ :return:
1025+ """
1026+ self ._touch_events .register_callback ('on_right_pressed' , callback , args )
1027+
1028+ def _start_touch_events_thread (self ) -> None :
1029+ """
1030+ Starts the touch events thread
1031+ :return:
1032+ """
1033+ if not self .__class__ ._touch_events_thread_running :
1034+ self .__class__ ._touch_events_thread_running = True
1035+ self .__class__ ._touch_events_thread_id = _thread .start_new_thread (self ._update_touch_events , (50 ,))
1036+
1037+ def _update_touch_events (self , delay_ : int = 100 ):
1038+ """
1039+ Updates the touch state so that touch events can be generated
1040+ :param delay_:
1041+ :return:
1042+ """
1043+ while True :
1044+ if self .is_on () and self ._touch_byte is not None :
1045+ self ._touch_events .update_touch_state (self ._touch_byte )
1046+ if not ArduinoAlvik ._touch_events_thread_running :
1047+ break
1048+ sleep_ms (delay_ )
1049+
1050+ @classmethod
1051+ def _stop_touch_events_thread (cls ):
1052+ """
1053+ Stops the touch events thread
1054+ :return:
1055+ """
1056+ cls ._touch_events_thread_running = False
1057+
9561058
9571059class _ArduinoAlvikWheel :
9581060
@@ -1065,3 +1167,159 @@ def set_color(self, red: bool, green: bool, blue: bool):
10651167 self ._led_state [0 ] = led_status
10661168 self ._packeter .packetC1B (ord ('L' ), led_status & 0xFF )
10671169 uart .write (self ._packeter .msg [0 :self ._packeter .msg_size ])
1170+
1171+
1172+ class _ArduinoAlvikEvents :
1173+ """
1174+ This is a generic events class
1175+ """
1176+
1177+ def __init__ (self ):
1178+ self ._callbacks = dict ()
1179+
1180+ def register_callback (self , event_name : str , callback : callable , args : tuple = None ):
1181+ """
1182+ Registers a callback to execute on an event
1183+ :param event_name:
1184+ :param callback: the callable
1185+ :param args: arguments tuple to pass to the callable. remember the comma! (value,)
1186+ :return:
1187+ """
1188+ self ._callbacks [event_name ] = (callback , args ,)
1189+
1190+ def has_callbacks (self ) -> bool :
1191+ """
1192+ True if the _callbacks dictionary has any callback registered
1193+ :return:
1194+ """
1195+ return bool (self ._callbacks )
1196+
1197+ def execute_callback (self , event_name : str ):
1198+ """
1199+ Executes the callback associated to the event_name
1200+ :param event_name:
1201+ :return:
1202+ """
1203+ if event_name not in self ._callbacks .keys ():
1204+ return
1205+ self ._callbacks [event_name ][0 ](* self ._callbacks [event_name ][1 ])
1206+
1207+
1208+ class _ArduinoAlvikTouchEvents (_ArduinoAlvikEvents ):
1209+ """
1210+ This is the event class to handle touch button events
1211+ """
1212+
1213+ available_events = ['on_ok_pressed' , 'on_cancel_pressed' ,
1214+ 'on_center_pressed' , 'on_left_pressed' ,
1215+ 'on_right_pressed' , 'on_up_pressed' ,
1216+ 'on_down_pressed' ]
1217+
1218+ def __init__ (self ):
1219+ self ._current_touch_state = 0
1220+ super ().__init__ ()
1221+
1222+ @staticmethod
1223+ def _is_ok_pressed (current_state , new_state ) -> bool :
1224+ """
1225+ True if OK was pressed
1226+ :param current_state:
1227+ :param new_state:
1228+ :return:
1229+ """
1230+ return not bool (current_state & 0b00000010 ) and bool (new_state & 0b00000010 )
1231+
1232+ @staticmethod
1233+ def _is_cancel_pressed (current_state , new_state ) -> bool :
1234+ """
1235+ True if CANCEL was pressed
1236+ :param current_state:
1237+ :param new_state:
1238+ :return:
1239+ """
1240+ return not bool (current_state & 0b00000100 ) and bool (new_state & 0b00000100 )
1241+
1242+ @staticmethod
1243+ def _is_center_pressed (current_state , new_state ) -> bool :
1244+ """
1245+ True if CENTER was pressed
1246+ :param current_state:
1247+ :param new_state:
1248+ :return:
1249+ """
1250+ return not bool (current_state & 0b00001000 ) and bool (new_state & 0b00001000 )
1251+
1252+ @staticmethod
1253+ def _is_up_pressed (current_state , new_state ) -> bool :
1254+ """
1255+ True if UP was pressed
1256+ :param current_state:
1257+ :param new_state:
1258+ :return:
1259+ """
1260+ return not bool (current_state & 0b00010000 ) and bool (new_state & 0b00010000 )
1261+
1262+ @staticmethod
1263+ def _is_left_pressed (current_state , new_state ) -> bool :
1264+ """
1265+ True if LEFT was pressed
1266+ :param current_state:
1267+ :param new_state:
1268+ :return:
1269+ """
1270+ return not bool (current_state & 0b00100000 ) and bool (new_state & 0b00100000 )
1271+
1272+ @staticmethod
1273+ def _is_down_pressed (current_state , new_state ) -> bool :
1274+ """
1275+ True if DOWN was pressed
1276+ :param current_state:
1277+ :param new_state:
1278+ :return:
1279+ """
1280+ return not bool (current_state & 0b01000000 ) and bool (new_state & 0b01000000 )
1281+
1282+ @staticmethod
1283+ def _is_right_pressed (current_state , new_state ) -> bool :
1284+ """
1285+ True if RIGHT was pressed
1286+ :param current_state:
1287+ :param new_state:
1288+ :return:
1289+ """
1290+ return not bool (current_state & 0b10000000 ) and bool (new_state & 0b10000000 )
1291+
1292+ def update_touch_state (self , touch_state : int ):
1293+ """
1294+ Updates the internal touch state and executes any possible callback
1295+ :param touch_state:
1296+ :return:
1297+ """
1298+
1299+ if self ._is_ok_pressed (self ._current_touch_state , touch_state ):
1300+ self .execute_callback ('on_ok_pressed' )
1301+
1302+ if self ._is_cancel_pressed (self ._current_touch_state , touch_state ):
1303+ self .execute_callback ('on_cancel_pressed' )
1304+
1305+ if self ._is_center_pressed (self ._current_touch_state , touch_state ):
1306+ self .execute_callback ('on_center_pressed' )
1307+
1308+ if self ._is_up_pressed (self ._current_touch_state , touch_state ):
1309+ self .execute_callback ('on_up_pressed' )
1310+
1311+ if self ._is_left_pressed (self ._current_touch_state , touch_state ):
1312+ self .execute_callback ('on_left_pressed' )
1313+
1314+ if self ._is_down_pressed (self ._current_touch_state , touch_state ):
1315+ self .execute_callback ('on_down_pressed' )
1316+
1317+ if self ._is_right_pressed (self ._current_touch_state , touch_state ):
1318+ self .execute_callback ('on_right_pressed' )
1319+
1320+ self ._current_touch_state = touch_state
1321+
1322+ def register_callback (self , event_name : str , callback : callable , args : tuple = None ):
1323+ if event_name not in self .__class__ .available_events :
1324+ return
1325+ super ().register_callback (event_name , callback , args )
0 commit comments