summaryrefslogtreecommitdiffstats
path: root/src/python
diff options
context:
space:
mode:
authorLennertW <4999638+LennertW@users.noreply.github.com>2022-08-06 18:39:43 +0200
committerLennertW <4999638+LennertW@users.noreply.github.com>2022-08-06 18:39:43 +0200
commitcbde04c9bc45ea54cc509a65247c62a82f64bca9 (patch)
tree5bc0900a502fc45c3c9cc778ed8a041056ae029e /src/python
parentREADME placeholder (diff)
downloadStarlink-FI-cbde04c9bc45ea54cc509a65247c62a82f64bca9.tar
Starlink-FI-cbde04c9bc45ea54cc509a65247c62a82f64bca9.tar.gz
Starlink-FI-cbde04c9bc45ea54cc509a65247c62a82f64bca9.tar.bz2
Starlink-FI-cbde04c9bc45ea54cc509a65247c62a82f64bca9.tar.lz
Starlink-FI-cbde04c9bc45ea54cc509a65247c62a82f64bca9.tar.xz
Starlink-FI-cbde04c9bc45ea54cc509a65247c62a82f64bca9.tar.zst
Starlink-FI-cbde04c9bc45ea54cc509a65247c62a82f64bca9.zip
Diffstat (limited to '')
-rw-r--r--src/python/example.py72
-rw-r--r--src/python/pulsegen.py130
2 files changed, 202 insertions, 0 deletions
diff --git a/src/python/example.py b/src/python/example.py
new file mode 100644
index 0000000..6995940
--- /dev/null
+++ b/src/python/example.py
@@ -0,0 +1,72 @@
+import numpy as np
+import time
+import serial
+from tqdm import tnrange, tqdm
+import random
+from pulsegen import PicoPulseGen
+
+# Open serial interface
+# I'm using this to detect when the glitch was successful
+try:
+ ser = serial.Serial('/dev/ttyUSB0', 115200)
+
+except Exception as e:
+ print('Could not open /dev/ttyUSB0')
+ exit()
+
+# Connect to modchip
+try:
+ glitcher = PicoPulseGen('/dev/ttyACM0')
+ logger.info('Connected to modchip')
+
+ # You have to figure out the trig_edges parameter
+ # You have to figure out ranges for the pulse_offset and pulse_width parameters
+ glitcher.trig_edges = 0
+ glitcher.pulse_offset = 0
+ glitcher.pulse_width = 0
+ glitcher.set_gpio(0)
+
+except Exception as e:
+ print('Could not connect to modchip')
+ exit()
+
+input("Press enter to start.")
+
+def generator():
+ while True:
+ yield
+
+idx = 0
+success = False
+for _ in tqdm(generator()):
+ if idx % 10 == 0:
+ # Pulse width and offset are expressed in number of cycles of the PIO state machine operating frequency (default in the provided fw is 250MHz).
+ glitch_width = random.randint(A, B) # You have to figure out good ranges here
+ glitch_offset = random.randint(C, D)
+
+ glitcher.pulse_offset = glitch_offset
+ glitcher.pulse_width = glitch_width
+
+ ser.reset_input_buffer()
+ glitcher.arm() # Arm the modchip, it will try to power up the UT and will wait for the number of set trigger pulses to occur before inserting a glitch
+ glitcher.wait_trig(timeout=5) # Waits for the modchip to signal it has triggered. The modchip will be disarmed if no glitch has occurred within 5 seconds.
+
+ time.sleep(0.55) # Have to wait for the second stage to start to see serial output
+ data = ser.read(ser.in_waiting)
+
+ if b'LENNERT' in data: # a check to determine if the glitch was successful. My BL2 has been modified to print LENNERT.
+ success = True
+ break
+
+ glitcher.set_gpio(0) # Disables the core voltage regulator. The modchip firmware will re-enable the regulator automatically on the next glitch attempt.
+ time.sleep(0.1)
+
+ idx += 1
+
+if success:
+ print('Glitch successul!')
+ logger.debug('%d, %d, %d' %(idx, glitch_width, glitch_offset))
+ logger.debug(data.decode('utf-8', 'ignore'))
+
+ser.close()
+glitcher.close() \ No newline at end of file
diff --git a/src/python/pulsegen.py b/src/python/pulsegen.py
new file mode 100644
index 0000000..161625a
--- /dev/null
+++ b/src/python/pulsegen.py
@@ -0,0 +1,130 @@
+import serial
+import time
+import signal
+
+class PicoPulseGen:
+ def __init__(self, port='/dev/ttyACM0'):
+ self._pulse_offset = 0
+ self._pulse_width = 0
+ self._trig_edges = 0
+
+ self.pico = serial.Serial(port, 115200)
+ time.sleep(0.1)
+ self.pico.write(b'S')
+
+ test = self.pico.readline()
+ if b'PulseGenerator' not in test:
+ raise ConnectionError('Could not connect to the PulseGenerator :(')
+
+ signal.signal(signal.SIGALRM, self.arm_abort)
+
+
+ @property
+ def pulse_offset(self):
+ return self._pulse_offset
+
+
+ @pulse_offset.setter
+ def pulse_offset(self, offset):
+ if type(offset) != int or offset < 0 or offset > 0xFFFFFFFF:
+ raise ValueError('Offset has to be an int between 0 and 0xFFFFFFFF')
+
+ self._pulse_offset = offset
+
+ self.pico.flushInput()
+ self.pico.write(b'O')
+ self.pico.write((self._pulse_offset).to_bytes(4, 'little'))
+ ret = self.pico.readline()
+ assert int(ret.strip()) == self._pulse_offset, ret
+
+
+ @property
+ def pulse_width(self):
+ return self._pulse_offset
+
+
+ @pulse_width.setter
+ def pulse_width(self, width):
+ if type(width) != int or width < 0 or width > 0xFFFFFFFF:
+ raise ValueError('Width has to be an int between 0 and 0xFFFFFFFF')
+
+ self._pulse_width = width
+
+ self.pico.flushInput()
+ self.pico.write(b'W')
+ self.pico.write((self._pulse_width).to_bytes(4, 'little'))
+ ret = self.pico.readline()
+ assert int(ret.strip()) == self._pulse_width, ret
+
+
+ @property
+ def trig_edges(self):
+ return self._trig_edges
+
+
+ @trig_edges.setter
+ def trig_edges(self, edges):
+ if type(edges) != int or edges < 0 or edges > 0xFFFFFFFF:
+ raise ValueError('Width has to be an int between 0 and 0xFFFFFFFF')
+
+ self._trig_edges = edges
+
+ self.pico.write(b'E')
+ self.pico.write((self._trig_edges).to_bytes(4, 'little'))
+ ret = self.pico.readline()
+ assert int(ret.strip()) == self._trig_edges, ret
+
+
+ def arm(self):
+ self.pico.write(b'A')
+ ret = self.pico.readline()
+ assert b'A' in ret
+
+
+ def wait_trig(self, timeout=5):
+ self.pico.write(b'B')
+ signal.alarm(timeout)
+ ret = self.pico.readline()
+ signal.alarm(0)
+ assert b'T' in ret
+
+
+ def arm_abort(self, signum, frame):
+ print('No trigger observed, disarming!')
+ self.pico.write(b'D')
+
+
+ def status(self):
+ self.pico.write(b'S')
+ ret = self.pico.readline()
+ print(ret.decode('utf-8'))
+
+
+ def set_gpio(self, state):
+ if type(state) != int or state < 0:
+ raise ValueError('State has to be zero (GPIO 0) or a positive value larger than zero (GPIO 1)')
+
+ self.pico.write(b'G')
+ self.pico.write(bytes([7])) # For now there is only one GPIO pin used for this functionality
+ if state:
+ self.pico.write(bytes([1]))
+ else:
+ self.pico.write(bytes([0]))
+
+ ret = self.pico.readline()
+ assert b'G' in ret
+
+
+ def read_gpios(self):
+ self.pico.write(b'R')
+ ret = self.pico.readline()
+ ret = int(ret.strip())
+ return ret
+
+
+ def close(self):
+ self.pico.close()
+
+
+ def __del__(self):
+ self.pico.close() \ No newline at end of file