/ CLUE_BLE_Morse_Code / code.py
code.py
1 # SPDX-FileCopyrightText: 2020 Carter Nelson for Adafruit Industries 2 # 3 # SPDX-License-Identifier: MIT 4 5 import time 6 import displayio 7 import terminalio 8 from adafruit_clue import clue 9 from adafruit_display_text import label 10 import adafruit_imageload 11 from adafruit_ble import BLERadio 12 from adafruit_ble.advertising.standard import ProvideServicesAdvertisement 13 from adafruit_ble.services.nordic import UARTService 14 15 #--| User Config |--------------------------------------------------- 16 MY_NAME = "ME" 17 FRIENDS_NAME = "FRIEND" 18 #--| User Config |--------------------------------------------------- 19 20 WAIT_FOR_DOUBLE = 0.05 21 DEBOUNCE = 0.25 22 23 # Define Morse Code dictionary 24 morse_code = { 25 ".-" : "A", "-..." : "B", "-.-." : "C", "-.." : "D", "." : "E", 26 "..-." : "F", "--." : "G", "...." : "H", ".." : "I", ".---" : "J", 27 "-.-" : "K", ".-.." : "L", "--" : "M", "-." : "N", "---" : "O", 28 ".--." : "P", "--.-" : "Q", ".-." : "R", "..." : "S", "-" : "T", 29 "..-" : "U", "...-" : "V", ".--" : "W", "-..-" : "X", "-.--" : "Y", 30 "--.." : "Z", 31 } 32 33 # BLE Radio Stuff 34 ble = BLERadio() 35 uart_service = UARTService() 36 advertisement = ProvideServicesAdvertisement(uart_service) 37 ble._adapter.name = MY_NAME #pylint: disable=protected-access 38 39 # Display Stuff 40 display = clue.display 41 disp_group = displayio.Group() 42 display.show(disp_group) 43 44 # Background BMP with the Morse Code cheat sheet 45 bmp, pal = adafruit_imageload.load("morse_bg.bmp", 46 bitmap=displayio.Bitmap, 47 palette=displayio.Palette) 48 disp_group.append(displayio.TileGrid(bmp, pixel_shader=pal)) 49 50 # Incoming messages show up here 51 in_label = label.Label(terminalio.FONT, text='A'*18, scale=2, 52 color=0x000000) 53 in_label.anchor_point = (0.5, 0) 54 in_label.anchored_position = (65, 12) 55 disp_group.append(in_label) 56 57 # Outging messages show up here 58 out_label = label.Label(terminalio.FONT, text='B'*18, scale=2, 59 color=0x000000) 60 out_label.anchor_point = (0.5, 0) 61 out_label.anchored_position = (65, 190) 62 disp_group.append(out_label) 63 64 # Morse Code entry happens here 65 edit_label = label.Label(terminalio.FONT, text='....', scale=2, 66 color=0x000000) 67 edit_label.anchor_point = (0.5, 0) 68 edit_label.anchored_position = (105, 222) 69 disp_group.append(edit_label) 70 71 def scan_and_connect(): 72 ''' 73 Advertise self while scanning for friend. If friend is found, can 74 connect by pressing A+B buttons. If friend connects first, then 75 just stop. 76 77 Return is a UART object that can be used for read/write. 78 ''' 79 80 print("Advertising.") 81 central = False 82 ble.start_advertising(advertisement) 83 84 print("Waiting.") 85 friend = None 86 while not ble.connected: 87 88 if friend is None: 89 print("Scanning.") 90 in_label.text = out_label.text = "Scanning..." 91 for adv in ble.start_scan(): 92 if ble.connected: 93 # Friend connected with us, we're done 94 ble.stop_scan() 95 break 96 if adv.complete_name == FRIENDS_NAME: 97 # Found friend, can stop scanning 98 ble.stop_scan() 99 friend = adv 100 print("Found", friend.complete_name) 101 in_label.text = "Found {}".format(friend.complete_name) 102 out_label.text = "A+B to connect" 103 break 104 else: 105 if clue.button_a and clue.button_b: 106 # Connect to friend 107 print("Connecting to", friend.complete_name) 108 ble.connect(friend) 109 central = True 110 111 # We're now connected, one way or the other 112 print("Stopping advertising.") 113 ble.stop_advertising() 114 115 # Return a UART object to use 116 if central: 117 print("Central - using my UART service.") 118 return uart_service 119 else: 120 print("Peripheral - connecting to their UART service.") 121 for connection in ble.connections: 122 if UARTService not in connection: 123 continue 124 return connection[UARTService] 125 126 #-------------------------- 127 # The main application loop 128 #-------------------------- 129 while True: 130 131 # Establish initial connection 132 uart = scan_and_connect() 133 134 print("Connected.") 135 136 code = '' 137 in_label.text = out_label.text = ' '*18 138 edit_label.text = ' '*4 139 done = False 140 141 # Run the chat while connected 142 while ble.connected: 143 144 # Check for incoming message 145 incoming_bytes = uart.in_waiting 146 if incoming_bytes: 147 bytes_in = uart.read(incoming_bytes) 148 print("Received: ", bytes_in) 149 in_label.text = in_label.text[incoming_bytes:] + bytes_in.decode() 150 151 # DOT (or done) 152 if clue.button_a: 153 start = time.monotonic() 154 while time.monotonic() - start < WAIT_FOR_DOUBLE: 155 if clue.button_b: 156 done = True 157 if not done and len(code) < 4: 158 print('.', end='') 159 code += '.' 160 edit_label.text = "{:4s}".format(code) 161 time.sleep(DEBOUNCE) 162 163 # DASH (or done) 164 if clue.button_b: 165 start = time.monotonic() 166 while time.monotonic() - start < WAIT_FOR_DOUBLE: 167 if clue.button_a: 168 done = True 169 if not done and len(code) < 4: 170 print('-', end='') 171 code += '-' 172 edit_label.text = "{:4s}".format(code) 173 time.sleep(DEBOUNCE) 174 175 # Turn Morse Code into letter and send 176 if done: 177 letter = morse_code.get(code, ' ') 178 print(' >', letter) 179 out_label.text = out_label.text[1:] + letter 180 uart.write(str.encode(letter)) 181 code = '' 182 edit_label.text = ' '*4 183 done = False 184 time.sleep(DEBOUNCE) 185 186 print("Disconnected.")