migration
This commit is contained in:
+6
-6
@@ -1,7 +1,7 @@
|
|||||||
.vscode
|
.vscode
|
||||||
.micropico
|
.micropico
|
||||||
.gitignore
|
.gitignore
|
||||||
PiPicoPATLFGGGGG.code-workspace
|
PiPicoPATLFGGGGG.code-workspace
|
||||||
dev
|
dev
|
||||||
ComicCode-Regular.*
|
ComicCode-Regular.*
|
||||||
logs
|
logs
|
||||||
+12
-12
@@ -1,12 +1,12 @@
|
|||||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||||
Version 2, December 2004
|
Version 2, December 2004
|
||||||
|
|
||||||
Everyone is permitted to copy and distribute verbatim or modified
|
Everyone is permitted to copy and distribute verbatim or modified
|
||||||
copies of this license document, and changing it is allowed as long
|
copies of this license document, and changing it is allowed as long
|
||||||
as the name is changed.
|
as the name is changed.
|
||||||
|
|
||||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
0. You just DO WHAT THE FUCK YOU WANT TO.
|
0. You just DO WHAT THE FUCK YOU WANT TO.
|
||||||
|
|
||||||
|
|||||||
@@ -1,114 +1,114 @@
|
|||||||
# SillyFilly Pi Pico W Power Analysis Tool
|
# SillyFilly Pi Pico W Power Analysis Tool
|
||||||
# LFGGGGGGGGGGG
|
# LFGGGGGGGGGGG
|
||||||
# FRONG
|
# FRONG
|
||||||
A tool for simplifying power analysis attacks against other gadgets.
|
A tool for simplifying power analysis attacks against other gadgets.
|
||||||
Built on the Raspberry Pi Pico W, it runs a PWM channel to do manual clock control on the nugget you're hacking, and then reads an ADC channel to measure voltage used at each clock cycle.
|
Built on the Raspberry Pi Pico W, it runs a PWM channel to do manual clock control on the nugget you're hacking, and then reads an ADC channel to measure voltage used at each clock cycle.
|
||||||
|
|
||||||
## Screenshots
|
## Screenshots
|
||||||
Config page
|
Config page
|
||||||

|

|
||||||
|
|
||||||
Running page
|
Running page
|
||||||

|

|
||||||
|
|
||||||
Serial terminal at boot
|
Serial terminal at boot
|
||||||

|

|
||||||
|
|
||||||
Serial terminal while sampling and looping
|
Serial terminal while sampling and looping
|
||||||

|

|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
Make sure you have Micropython installed on your Pico W.
|
Make sure you have Micropython installed on your Pico W.
|
||||||
Open up your Pico W in your favorite IDE (Thonny and VS Code are commonly used) and upload main.py.
|
Open up your Pico W in your favorite IDE (Thonny and VS Code are commonly used) and upload main.py.
|
||||||
If you're having trouble, see the official [Raspberry Pi Pico W Getting Started Page](https://projects.raspberrypi.org/en/projects/get-started-pico-w)
|
If you're having trouble, see the official [Raspberry Pi Pico W Getting Started Page](https://projects.raspberrypi.org/en/projects/get-started-pico-w)
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
1) Optional: edit the `power_analysis_pin` and `clock_pulse_pin` variables as you see fit
|
1) Optional: edit the `power_analysis_pin` and `clock_pulse_pin` variables as you see fit
|
||||||
2) Edit the `ssid` and `password` variables with your wifi name (ssid) and the password
|
2) Edit the `ssid` and `password` variables with your wifi name (ssid) and the password
|
||||||
3) Set up the Pico W with pins on a breadboard, connect your power_analysis_pin and clock_pulse pin to the nugget (See Theory and Method)
|
3) Set up the Pico W with pins on a breadboard, connect your power_analysis_pin and clock_pulse pin to the nugget (See Theory and Method)
|
||||||
3) Plug the Pico W to USB of your computer
|
3) Plug the Pico W to USB of your computer
|
||||||
4) Open the serial terminal of the Pico W
|
4) Open the serial terminal of the Pico W
|
||||||
5) Reset the Pico W
|
5) Reset the Pico W
|
||||||
6) When the Pico W connects, it will display a message like `Open web browser and navigate to http://x.x.x.x` Open a web browser on the same network and navigate to that address
|
6) When the Pico W connects, it will display a message like `Open web browser and navigate to http://x.x.x.x` Open a web browser on the same network and navigate to that address
|
||||||
7) Configure the options on the page to your liking (see below under Options)
|
7) Configure the options on the page to your liking (see below under Options)
|
||||||
|
|
||||||
|
|
||||||
## Options
|
## Options
|
||||||
### main.py
|
### main.py
|
||||||
`power_analysis_pin`
|
`power_analysis_pin`
|
||||||
This is the pin that is reading the power usage from the device
|
This is the pin that is reading the power usage from the device
|
||||||
Defaults to GPIO 28
|
Defaults to GPIO 28
|
||||||
|
|
||||||
`clock_pulse_pin`
|
`clock_pulse_pin`
|
||||||
This pin provides the clock signal that you will be using to manually take control of the nuggets clock
|
This pin provides the clock signal that you will be using to manually take control of the nuggets clock
|
||||||
Defaults to GPIO 20
|
Defaults to GPIO 20
|
||||||
|
|
||||||
`ssid`
|
`ssid`
|
||||||
This is your wifi network name. Only bgn supported (2.4GHz)
|
This is your wifi network name. Only bgn supported (2.4GHz)
|
||||||
Dont forget the 's around the name
|
Dont forget the 's around the name
|
||||||
|
|
||||||
`password`
|
`password`
|
||||||
Your wifi password
|
Your wifi password
|
||||||
Dont forget the 's around the password
|
Dont forget the 's around the password
|
||||||
|
|
||||||
`power_on_pin`
|
`power_on_pin`
|
||||||
The pin that toggles 3.3v on and off to activate and reset the nugget board
|
The pin that toggles 3.3v on and off to activate and reset the nugget board
|
||||||
|
|
||||||
`seconds_awake`
|
`seconds_awake`
|
||||||
The number of seconds to turn on power_on_pin before resetting
|
The number of seconds to turn on power_on_pin before resetting
|
||||||
|
|
||||||
### On the Webpage
|
### On the Webpage
|
||||||
`Duty Cycle`
|
`Duty Cycle`
|
||||||
The Percentage of the time that the clock is on vs off
|
The Percentage of the time that the clock is on vs off
|
||||||
50% is by far the most common, it makes a normal square wave and is the default output
|
50% is by far the most common, it makes a normal square wave and is the default output
|
||||||
for most oscilators that you will be replacing
|
for most oscilators that you will be replacing
|
||||||
|
|
||||||
`Frequency`
|
`Frequency`
|
||||||
Frequency in Hertz (Hz)
|
Frequency in Hertz (Hz)
|
||||||
How many times per second you want your nuggets clock to pulse
|
How many times per second you want your nuggets clock to pulse
|
||||||
Dont make this too high
|
Dont make this too high
|
||||||
|
|
||||||
`Samples Per Manual Clock Pulse`
|
`Samples Per Manual Clock Pulse`
|
||||||
This is how many times per clock pulse to sample the nuggets power usage
|
This is how many times per clock pulse to sample the nuggets power usage
|
||||||
Dont make this too high
|
Dont make this too high
|
||||||
|
|
||||||
## Hardware Needed
|
## Hardware Needed
|
||||||
1) Raspberry Pi Pico W or Raspberry Pi Pico WH
|
1) Raspberry Pi Pico W or Raspberry Pi Pico WH
|
||||||
2) Pins
|
2) Pins
|
||||||
3) Breadboard
|
3) Breadboard
|
||||||
4) Small capacitior (470uF is fine or anywhere within that range)
|
4) Small capacitior (470uF is fine or anywhere within that range)
|
||||||
5) Wires
|
5) Wires
|
||||||
6) Optional: spikey probes
|
6) Optional: spikey probes
|
||||||
|
|
||||||
## Theory
|
## Theory
|
||||||
Power analysis attacks are very simple in concept.
|
Power analysis attacks are very simple in concept.
|
||||||
The idea is monitoring the amount of power a device uses very carefully to get some data leaked.
|
The idea is monitoring the amount of power a device uses very carefully to get some data leaked.
|
||||||
Two things are most important during these attacks:
|
Two things are most important during these attacks:
|
||||||
1) Getting the most accurate, raw read of the power usage at a high sample rate
|
1) Getting the most accurate, raw read of the power usage at a high sample rate
|
||||||
2) Controlling the clock of the device to slow down the processor enough to get the readings
|
2) Controlling the clock of the device to slow down the processor enough to get the readings
|
||||||
|
|
||||||
To accomplish #1, we will get our power reading probe as close to the action of the processor as possible, while als adding a capacitor ground, which will pull any remaining juice out of the system.
|
To accomplish #1, we will get our power reading probe as close to the action of the processor as possible, while als adding a capacitor ground, which will pull any remaining juice out of the system.
|
||||||
|
|
||||||
For #2, we need to remove the builtin crystal oscilator and replace that connection with our clock pulse probe.
|
For #2, we need to remove the builtin crystal oscilator and replace that connection with our clock pulse probe.
|
||||||
|
|
||||||
For this example, I will describe a firmware decryption power analysis attack.
|
For this example, I will describe a firmware decryption power analysis attack.
|
||||||
|
|
||||||
Scenario: You have and ESP32-S3 based device with flash and bootloader encryption set up on it. You Can remove the RF sheield and get a raw dump of the flash chip with a SOP8 test clip and a programmer, but the data is encrypted.
|
Scenario: You have and ESP32-S3 based device with flash and bootloader encryption set up on it. You Can remove the RF sheield and get a raw dump of the flash chip with a SOP8 test clip and a programmer, but the data is encrypted.
|
||||||
|
|
||||||
## Method
|
## Method
|
||||||
1) We disassemble the device to the bare board we're interested in
|
1) We disassemble the device to the bare board we're interested in
|
||||||
2) Then remove the RF shield and crystal oscilator from the ESP32-S3 via reflow
|
2) Then remove the RF shield and crystal oscilator from the ESP32-S3 via reflow
|
||||||
3) Clip a SOP8 test clip on the 8pin flash chip and dump the encrypted data with a programmer like a CH431a or T48
|
3) Clip a SOP8 test clip on the 8pin flash chip and dump the encrypted data with a programmer like a CH431a or T48
|
||||||
4) Set up the breadboard with the Pico W.
|
4) Set up the breadboard with the Pico W.
|
||||||
5) Place the clock_pulse_pin probe where the crystal oscillator used to be
|
5) Place the clock_pulse_pin probe where the crystal oscillator used to be
|
||||||
6) Place power_analysis_pin probe on the rawest vin power spot you can find
|
6) Place power_analysis_pin probe on the rawest vin power spot you can find
|
||||||
7) Run the Pico W (see Usage)
|
7) Run the Pico W (see Usage)
|
||||||
8) Dump serial data to some manner of logger Todo: figure out this tooling
|
8) Dump serial data to some manner of logger Todo: figure out this tooling
|
||||||
9) Perform statistical attack to dump key! Todo: automate and figure out tooling
|
9) Perform statistical attack to dump key! Todo: automate and figure out tooling
|
||||||
|
|
||||||
Todo: Make readme not suck
|
Todo: Make readme not suck
|
||||||
--
|
--
|
||||||
|
|
||||||
Distributed under the [WTFPL - The Do What the Fuck You Want to Public License](http://www.wtfpl.net/)
|
Distributed under the [WTFPL - The Do What the Fuck You Want to Public License](http://www.wtfpl.net/)
|
||||||
See [COPYING.txt](COPYING.txt)
|
See [COPYING.txt](COPYING.txt)
|
||||||

|
[](http://www.wtfpl.net/)
|
||||||
@@ -1,259 +1,259 @@
|
|||||||
import network
|
import network
|
||||||
import socket
|
import socket
|
||||||
import machine
|
import machine
|
||||||
from machine import Timer
|
from machine import Timer
|
||||||
import utime
|
import utime
|
||||||
import _thread
|
import _thread
|
||||||
import math
|
import math
|
||||||
|
|
||||||
# gpio pin to read power analysis off of (int)
|
# gpio pin to read power analysis off of (int)
|
||||||
# reads 16bit (0-65535) between 0.0v and 3.3v
|
# reads 16bit (0-65535) between 0.0v and 3.3v
|
||||||
# (16 bit is phony, real read is 12 bit)
|
# (16 bit is phony, real read is 12 bit)
|
||||||
power_analysis_pin = 28
|
power_analysis_pin = 28
|
||||||
|
|
||||||
# output gpio pin generating clock pulse
|
# output gpio pin generating clock pulse
|
||||||
clock_pulse_pin = 20
|
clock_pulse_pin = 20
|
||||||
|
|
||||||
# this pin gets power and toggles off and on every X PWM cycles
|
# this pin gets power and toggles off and on every X PWM cycles
|
||||||
# it powers the board you're targeting
|
# it powers the board you're targeting
|
||||||
power_on_pin = 2
|
power_on_pin = 2
|
||||||
|
|
||||||
# how many seconds to power the board before reset
|
# how many seconds to power the board before reset
|
||||||
seconds_awake = 3
|
seconds_awake = 3
|
||||||
|
|
||||||
# Wi-Fi credentials
|
# Wi-Fi credentials
|
||||||
ssid = 'your-wifi-name-here'
|
ssid = 'your-wifi-name-here'
|
||||||
password = 'your-wifi-password-here'
|
password = 'your-wifi-password-here'
|
||||||
|
|
||||||
# == Clock Pulse Genertor == #
|
# == Clock Pulse Genertor == #
|
||||||
# starts a pwm
|
# starts a pwm
|
||||||
# usage do_pwm(int gpio_pin, float duty_cycle, int hertz frequency, int samples_per_clock_pulse)
|
# usage do_pwm(int gpio_pin, float duty_cycle, int hertz frequency, int samples_per_clock_pulse)
|
||||||
def do_pwm(outpin, duty_cycle, frequency):
|
def do_pwm(outpin, duty_cycle, frequency):
|
||||||
global pwm_pin
|
global pwm_pin
|
||||||
output_pin = machine.Pin(outpin)
|
output_pin = machine.Pin(outpin)
|
||||||
|
|
||||||
# configure pwm
|
# configure pwm
|
||||||
pwm_pin = machine.PWM(output_pin)
|
pwm_pin = machine.PWM(output_pin)
|
||||||
pwm_pin.freq(frequency) # frequency in Hz
|
pwm_pin.freq(frequency) # frequency in Hz
|
||||||
pwm_duty = math.floor(duty_cycle*65535) # duty cycle is a uint 16bit
|
pwm_duty = math.floor(duty_cycle*65535) # duty cycle is a uint 16bit
|
||||||
|
|
||||||
# run da pwm
|
# run da pwm
|
||||||
pwm_pin.duty_u16(pwm_duty)
|
pwm_pin.duty_u16(pwm_duty)
|
||||||
|
|
||||||
# us of sleep calculate4d by ceil(1000000 / (frequency_in_Hz * samples_per_pulse))
|
# us of sleep calculate4d by ceil(1000000 / (frequency_in_Hz * samples_per_pulse))
|
||||||
# 1000000 is one million, 1,000,000 or 10^6
|
# 1000000 is one million, 1,000,000 or 10^6
|
||||||
def us_samples(frequency, samples_per_pulse):
|
def us_samples(frequency, samples_per_pulse):
|
||||||
return math.ceil(1000000/(frequency*samples_per_pulse))
|
return math.ceil(1000000/(frequency*samples_per_pulse))
|
||||||
|
|
||||||
# == Read Value off of device == #
|
# == Read Value off of device == #
|
||||||
# uses ADC, 16bit output is phony, is actualloy 12bit.
|
# uses ADC, 16bit output is phony, is actualloy 12bit.
|
||||||
kill = False # for the thread killing hack
|
kill = False # for the thread killing hack
|
||||||
def do_adc(adcpin, frequency, samples_per_pulse):
|
def do_adc(adcpin, frequency, samples_per_pulse):
|
||||||
analog_value = machine.ADC(adcpin)
|
analog_value = machine.ADC(adcpin)
|
||||||
us_sample = us_samples(frequency, samples_per_pulse)
|
us_sample = us_samples(frequency, samples_per_pulse)
|
||||||
|
|
||||||
global kill
|
global kill
|
||||||
while True:
|
while True:
|
||||||
reading = analog_value.read_u16() # do the actual reading, actual precision is 12bit
|
reading = analog_value.read_u16() # do the actual reading, actual precision is 12bit
|
||||||
print(reading,',',sep='')
|
print(reading,',',sep='')
|
||||||
utime.sleep_us(us_sample)
|
utime.sleep_us(us_sample)
|
||||||
|
|
||||||
# just keep checking if kill is set to True by reset_init()
|
# just keep checking if kill is set to True by reset_init()
|
||||||
# if it is True, reset kill to False, kill the thread, and break for good measure
|
# if it is True, reset kill to False, kill the thread, and break for good measure
|
||||||
if kill is True:
|
if kill is True:
|
||||||
kill = False
|
kill = False
|
||||||
_thread.exit()
|
_thread.exit()
|
||||||
break
|
break
|
||||||
|
|
||||||
# HTML template for the webpage
|
# HTML template for the webpage
|
||||||
header = """
|
header = """
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>SillyFilly Pi Pico Power Analysis Tool (LFFGGGGG)</title>
|
<title>SillyFilly Pi Pico Power Analysis Tool (LFFGGGGG)</title>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<!-- todo: actually host this font file somewhere lmfao -->
|
<!-- todo: actually host this font file somewhere lmfao -->
|
||||||
<link rel="preload" href="http://10.0.0.80/ComicCode-Regular.woff2" as="font" type="font/woff2" crossorigin>
|
<link rel="preload" href="http://10.0.0.80/ComicCode-Regular.woff2" as="font" type="font/woff2" crossorigin>
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
font-family: 'Comic Code', 'Comic Sans MS', Monospace;
|
font-family: 'Comic Code', 'Comic Sans MS', Monospace;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
form, div {
|
form, div {
|
||||||
width: 80%;
|
width: 80%;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
font-size: 1.15em;'
|
font-size: 1.15em;'
|
||||||
}
|
}
|
||||||
|
|
||||||
form input[type='number'] {
|
form input[type='number'] {
|
||||||
width: 3.6em;
|
width: 3.6em;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
footer = """
|
footer = """
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def default_webpage():
|
def default_webpage():
|
||||||
template = f"""
|
template = f"""
|
||||||
{header}
|
{header}
|
||||||
<form action="/action">
|
<form action="/action">
|
||||||
<h1>SillyFilly Pi Pico Power Analysis Tool (LFFGGGGG)</h1>
|
<h1>SillyFilly Pi Pico Power Analysis Tool (LFFGGGGG)</h1>
|
||||||
<b>Config:</b><br>
|
<b>Config:</b><br>
|
||||||
Duty Cycle<br><input id="duty_cycle" name="duty_cycle" type="range" min="0" max="1" step="0.01" value="0.5"> <output id="duty_cycle_output">50%</output><br><br>
|
Duty Cycle<br><input id="duty_cycle" name="duty_cycle" type="range" min="0" max="1" step="0.01" value="0.5"> <output id="duty_cycle_output">50%</output><br><br>
|
||||||
Frequency (Hz)<br><input type="number" size="5" name="freq" value="2000"><br><br>
|
Frequency (Hz)<br><input type="number" size="5" name="freq" value="2000"><br><br>
|
||||||
Samples Per Clock Pulse:<br> <input type="number" size="5" id="samples_per_pulse" name="samples_per_pulse" value="5"><br><br>
|
Samples Per Clock Pulse:<br> <input type="number" size="5" id="samples_per_pulse" name="samples_per_pulse" value="5"><br><br>
|
||||||
<input type="submit" value="Go, Baby, Go!">
|
<input type="submit" value="Go, Baby, Go!">
|
||||||
</form>
|
</form>
|
||||||
<script>
|
<script>
|
||||||
const value = document.querySelector("#duty_cycle_output");
|
const value = document.querySelector("#duty_cycle_output");
|
||||||
const input = document.querySelector("#duty_cycle");
|
const input = document.querySelector("#duty_cycle");
|
||||||
|
|
||||||
input.addEventListener("input", (event) => {{
|
input.addEventListener("input", (event) => {{
|
||||||
value.textContent = (event.target.value*100)+"%";
|
value.textContent = (event.target.value*100)+"%";
|
||||||
}});
|
}});
|
||||||
</script>
|
</script>
|
||||||
{footer}
|
{footer}
|
||||||
"""
|
"""
|
||||||
return str(template)
|
return str(template)
|
||||||
|
|
||||||
def running_webpage(outpin, adcpin, duty_cycle, frequency, samples_per_pulse, loop_time):
|
def running_webpage(outpin, adcpin, duty_cycle, frequency, samples_per_pulse, loop_time):
|
||||||
dutyy = duty_cycle*100
|
dutyy = duty_cycle*100
|
||||||
us_sample = us_samples(frequency, samples_per_pulse)
|
us_sample = us_samples(frequency, samples_per_pulse)
|
||||||
template = f"""
|
template = f"""
|
||||||
{header}
|
{header}
|
||||||
<div id="sillyrunninfg">
|
<div id="sillyrunninfg">
|
||||||
<h1>SillyFilly Pi Pico Power Analysis Tool (LFFGGGGG)</h1>
|
<h1>SillyFilly Pi Pico Power Analysis Tool (LFFGGGGG)</h1>
|
||||||
<h2>WE RUNNING NOWWWWW LFGGGGGGGGGGGGG</h2>
|
<h2>WE RUNNING NOWWWWW LFGGGGGGGGGGGGG</h2>
|
||||||
<p>
|
<p>
|
||||||
Clock Pulse Pin: <b>{outpin}</b><br>
|
Clock Pulse Pin: <b>{outpin}</b><br>
|
||||||
Power Analysis Pin: <b>{adcpin}</b><br>
|
Power Analysis Pin: <b>{adcpin}</b><br>
|
||||||
Power On Pin:{power_on_pin} <b></b><br><br><br>
|
Power On Pin:{power_on_pin} <b></b><br><br><br>
|
||||||
|
|
||||||
Frequency: <b>{frequency}Hz</b> (Duty Cycle: <b>{dutyy}%</b><br>
|
Frequency: <b>{frequency}Hz</b> (Duty Cycle: <b>{dutyy}%</b><br>
|
||||||
Samples Per Pulse: <b>{samples_per_pulse}</b><br>
|
Samples Per Pulse: <b>{samples_per_pulse}</b><br>
|
||||||
Delay Between Samples: <b>{us_sample}us</b><br><br>
|
Delay Between Samples: <b>{us_sample}us</b><br><br>
|
||||||
Loop length: <b>{loop_time}</b><br><br><br>
|
Loop length: <b>{loop_time}</b><br><br><br>
|
||||||
<b>LFGGGGGGGG FRONG</b>
|
<b>LFGGGGGGGG FRONG</b>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
{footer}
|
{footer}
|
||||||
"""
|
"""
|
||||||
return str(template)
|
return str(template)
|
||||||
|
|
||||||
print("Board Started or Reset\n===========\n\n")
|
print("Board Started or Reset\n===========\n\n")
|
||||||
|
|
||||||
toggle_power = machine.Pin(power_on_pin, machine.Pin.OUT)
|
toggle_power = machine.Pin(power_on_pin, machine.Pin.OUT)
|
||||||
toggle_power.value(0)
|
toggle_power.value(0)
|
||||||
|
|
||||||
# I like to have the LED on :3
|
# I like to have the LED on :3
|
||||||
led = machine.Pin('LED', machine.Pin.OUT)
|
led = machine.Pin('LED', machine.Pin.OUT)
|
||||||
led.value(1)
|
led.value(1)
|
||||||
|
|
||||||
# do da thingggggssssss for da loooop
|
# do da thingggggssssss for da loooop
|
||||||
def reset_init(t):
|
def reset_init(t):
|
||||||
global kill
|
global kill
|
||||||
kill = True # kill da adc thread
|
kill = True # kill da adc thread
|
||||||
toggle_power.value(0) # kill power on pin
|
toggle_power.value(0) # kill power on pin
|
||||||
print("==Looping==")
|
print("==Looping==")
|
||||||
pwm_pin.deinit() # stop pwm
|
pwm_pin.deinit() # stop pwm
|
||||||
utime.sleep(1)
|
utime.sleep(1)
|
||||||
toggle_power.value(1) # re-enable power on pin
|
toggle_power.value(1) # re-enable power on pin
|
||||||
do_pwm(clock_pulse_pin, duty_cycle_in, freq_in) # restart pwm
|
do_pwm(clock_pulse_pin, duty_cycle_in, freq_in) # restart pwm
|
||||||
|
|
||||||
# restart da threaddyyyyy
|
# restart da threaddyyyyy
|
||||||
_thread.start_new_thread(do_adc, (power_analysis_pin, freq_in, samples_per_pulse_in))
|
_thread.start_new_thread(do_adc, (power_analysis_pin, freq_in, samples_per_pulse_in))
|
||||||
|
|
||||||
# Connect to WLAN
|
# Connect to WLAN
|
||||||
wlan = network.WLAN(network.STA_IF)
|
wlan = network.WLAN(network.STA_IF)
|
||||||
wlan.active(True)
|
wlan.active(True)
|
||||||
wlan.connect(ssid, password)
|
wlan.connect(ssid, password)
|
||||||
|
|
||||||
# Wait for Wi-Fi connection
|
# Wait for Wi-Fi connection
|
||||||
connection_timeout = 9
|
connection_timeout = 9
|
||||||
while connection_timeout > 0:
|
while connection_timeout > 0:
|
||||||
if wlan.status() >= 3:
|
if wlan.status() >= 3:
|
||||||
break
|
break
|
||||||
connection_timeout -= 1
|
connection_timeout -= 1
|
||||||
print('Waiting for Wi-Fi connection...')
|
print('Waiting for Wi-Fi connection...')
|
||||||
utime.sleep(1)
|
utime.sleep(1)
|
||||||
|
|
||||||
# Check if connection is successful
|
# Check if connection is successful
|
||||||
if wlan.status() != 3:
|
if wlan.status() != 3:
|
||||||
raise RuntimeError('Failed to establish a network connection')
|
raise RuntimeError('Failed to establish a network connection')
|
||||||
else:
|
else:
|
||||||
print('Connection successful!')
|
print('Connection successful!')
|
||||||
network_info = wlan.ifconfig()
|
network_info = wlan.ifconfig()
|
||||||
print(f"\n\nOpen web browser and navigate to http://{network_info[0]}\n\n")
|
print(f"\n\nOpen web browser and navigate to http://{network_info[0]}\n\n")
|
||||||
|
|
||||||
# Set up socket and start listening
|
# Set up socket and start listening
|
||||||
addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1]
|
addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1]
|
||||||
s = socket.socket()
|
s = socket.socket()
|
||||||
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||||
s.bind(addr)
|
s.bind(addr)
|
||||||
s.listen()
|
s.listen()
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
conn, addr = s.accept()
|
conn, addr = s.accept()
|
||||||
request = conn.recv(1024)
|
request = conn.recv(1024)
|
||||||
request = str(request)
|
request = str(request)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
fullreq = request.split()
|
fullreq = request.split()
|
||||||
request = fullreq[1]
|
request = fullreq[1]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Process the action page!
|
# Process the action page!
|
||||||
if request.startswith('/action?', 0):
|
if request.startswith('/action?', 0):
|
||||||
# parse the request path to extract da GET vars
|
# parse the request path to extract da GET vars
|
||||||
req_string = request.split('?')[1]
|
req_string = request.split('?')[1]
|
||||||
req_vars = req_string.split('&')
|
req_vars = req_string.split('&')
|
||||||
for f in req_vars:
|
for f in req_vars:
|
||||||
req_split = f.split('=')
|
req_split = f.split('=')
|
||||||
# Type strict whitelist for safety and compatibility
|
# Type strict whitelist for safety and compatibility
|
||||||
if req_split[0] == 'duty_cycle':
|
if req_split[0] == 'duty_cycle':
|
||||||
duty_cycle_in = float(req_split[1])
|
duty_cycle_in = float(req_split[1])
|
||||||
elif req_split[0] == 'freq':
|
elif req_split[0] == 'freq':
|
||||||
freq_in = int(req_split[1])
|
freq_in = int(req_split[1])
|
||||||
elif req_split[0] == 'samples_per_pulse':
|
elif req_split[0] == 'samples_per_pulse':
|
||||||
samples_per_pulse_in = int(req_split[1])
|
samples_per_pulse_in = int(req_split[1])
|
||||||
|
|
||||||
loop_time = (seconds_awake-1)*1000 # the -1 is because reset_init() adds a 1 second delay
|
loop_time = (seconds_awake-1)*1000 # the -1 is because reset_init() adds a 1 second delay
|
||||||
dutyyy = duty_cycle_in*100
|
dutyyy = duty_cycle_in*100
|
||||||
us_sample = us_samples(freq_in, samples_per_pulse_in)
|
us_sample = us_samples(freq_in, samples_per_pulse_in)
|
||||||
|
|
||||||
print(f"Clock pulse pin: {clock_pulse_pin}\n\nPower analysis pin: {power_analysis_pin}\n\nPower on pin: {power_on_pin}\n\nDuty cycle: {duty_cycle_in}%\n\nFrequency: {freq_in}Hz\n\nSamples per clock pulse: {samples_per_pulse_in}\n\nTime between samples: {us_sample}us\n\nLoop length: {loop_time}ms\n\n")
|
print(f"Clock pulse pin: {clock_pulse_pin}\n\nPower analysis pin: {power_analysis_pin}\n\nPower on pin: {power_on_pin}\n\nDuty cycle: {duty_cycle_in}%\n\nFrequency: {freq_in}Hz\n\nSamples per clock pulse: {samples_per_pulse_in}\n\nTime between samples: {us_sample}us\n\nLoop length: {loop_time}ms\n\n")
|
||||||
|
|
||||||
# run the clock pulse (PWM) task
|
# run the clock pulse (PWM) task
|
||||||
do_pwm(clock_pulse_pin, duty_cycle_in, freq_in)
|
do_pwm(clock_pulse_pin, duty_cycle_in, freq_in)
|
||||||
|
|
||||||
# fork the voltage measuring ADC reading to the second core
|
# fork the voltage measuring ADC reading to the second core
|
||||||
_thread.start_new_thread(do_adc, (power_analysis_pin, freq_in, samples_per_pulse_in))
|
_thread.start_new_thread(do_adc, (power_analysis_pin, freq_in, samples_per_pulse_in))
|
||||||
|
|
||||||
Timer(mode=Timer.PERIODIC, period=loop_time, callback=reset_init)
|
Timer(mode=Timer.PERIODIC, period=loop_time, callback=reset_init)
|
||||||
|
|
||||||
# outpin, adcpin, duty_cycle, frequency, samples_per_pulse, loop_time
|
# outpin, adcpin, duty_cycle, frequency, samples_per_pulse, loop_time
|
||||||
response = running_webpage(clock_pulse_pin, power_analysis_pin, dutyyy, freq_in, samples_per_pulse_in, loop_time)
|
response = running_webpage(clock_pulse_pin, power_analysis_pin, dutyyy, freq_in, samples_per_pulse_in, loop_time)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
response = default_webpage()
|
response = default_webpage()
|
||||||
|
|
||||||
# Send the HTTP response and close the conn
|
# Send the HTTP response and close the conn
|
||||||
conn.send('HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n')
|
conn.send('HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n')
|
||||||
conn.send(response)
|
conn.send(response)
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
conn.close()
|
conn.close()
|
||||||
print('Connection closed')
|
print('Connection closed')
|
||||||
Reference in New Issue
Block a user