Compare commits
10 commits
59a9758a63
...
4e50929f9c
| Author | SHA1 | Date | |
|---|---|---|---|
| 4e50929f9c | |||
| 057c6f51fc | |||
| 2ecd603db9 | |||
| 81e30791b0 | |||
| adc5e6a078 | |||
| 7ef7a0bfef | |||
| 58c74ebc86 | |||
| e8bcd7c994 | |||
| eed427f986 | |||
| 9af30ef829 |
10 changed files with 431 additions and 47 deletions
6
.gitignore
vendored
6
.gitignore
vendored
|
|
@ -163,3 +163,9 @@ tags
|
||||||
[._]*.un~
|
[._]*.un~
|
||||||
|
|
||||||
# End of https://www.toptal.com/developers/gitignore/api/vim,python
|
# End of https://www.toptal.com/developers/gitignore/api/vim,python
|
||||||
|
|
||||||
|
# Binary files
|
||||||
|
*.bin
|
||||||
|
|
||||||
|
# Mac
|
||||||
|
/**/.DS_Store
|
||||||
|
|
|
||||||
6
.vim/coc-settings.json
Normal file
6
.vim/coc-settings.json
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"python.linting.pylintEnabled": true,
|
||||||
|
"python.linting.mypyEnabled": false,
|
||||||
|
"python.linting.enabled": true,
|
||||||
|
"python.formatting.provider": "black"
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,7 @@
|
||||||
# eeprom_programmer
|
# eeprom_programmer
|
||||||
A very basic EEPROM programmer, compatible with chips with up to 15 address lines.
|
A very basic EEPROM programmer, compatible with chips with up to 15 address lines.
|
||||||
|
|
||||||
|
# Protoboard assembly
|
||||||
|

|
||||||
|
|
||||||
##### This project was inspired by and based on [Ben Eater's programmer](https://github.com/beneater/eeprom-programmer)
|
##### This project was inspired by and based on [Ben Eater's programmer](https://github.com/beneater/eeprom-programmer)
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,70 @@
|
||||||
// Digital pins 8 to 13 correspond to PB0 to PB5
|
// Digital pins 8 to 13 correspond to PB0 to PB5
|
||||||
|
|
||||||
byte lastOp;
|
byte lastOp;
|
||||||
|
int lastAddressWritten;
|
||||||
|
byte lastDataWritten;
|
||||||
|
bool isFirstWrite = true;
|
||||||
|
|
||||||
static char printBuff[128];
|
static char printBuff[128];
|
||||||
|
|
||||||
|
void program();
|
||||||
|
void dump();
|
||||||
|
void erase();
|
||||||
|
|
||||||
|
void dumpFirts256Bytes() {
|
||||||
|
byte data;
|
||||||
|
Serial.println("Reading EEPROM");
|
||||||
|
for (int addr = 0; addr < 256; addr += 16) {
|
||||||
|
sprintf(printBuff, "%04x:", addr);
|
||||||
|
Serial.print(printBuff);
|
||||||
|
for (int offset = 0; offset < 16; offset++) {
|
||||||
|
sprintf(printBuff, " %02x", readEEPROM(addr + offset));
|
||||||
|
Serial.print(printBuff);
|
||||||
|
}
|
||||||
|
Serial.println();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
// put your setup code here, to run once:
|
||||||
|
pinMode(SHIFT_DATA, OUTPUT);
|
||||||
|
pinMode(SHIFT_CLK, OUTPUT);
|
||||||
|
pinMode(SHIFT_LATCH, OUTPUT);
|
||||||
|
|
||||||
|
digitalWrite(EEPROM_WE, HIGH);
|
||||||
|
pinMode(EEPROM_WE, OUTPUT);
|
||||||
|
|
||||||
|
// Setting an invalid value.
|
||||||
|
lastOp = -1;
|
||||||
|
|
||||||
|
Serial.begin(115200);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
static byte command;
|
||||||
|
// The loop function only process commands.
|
||||||
|
while (Serial.available() == 0);
|
||||||
|
|
||||||
|
command = Serial.read();
|
||||||
|
|
||||||
|
switch(command) {
|
||||||
|
case 0x00:
|
||||||
|
// Program the eeprom.
|
||||||
|
program();
|
||||||
|
break;
|
||||||
|
case 0x01:
|
||||||
|
// Dump the eeprom.
|
||||||
|
dump();
|
||||||
|
break;
|
||||||
|
case 0x02:
|
||||||
|
// Erase the EEPROM (fill with 0xFF).
|
||||||
|
erase();
|
||||||
|
default:
|
||||||
|
// Ignore invalid commands.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void latchOutput() {
|
void latchOutput() {
|
||||||
static byte latchMask = 0b00010000;
|
static byte latchMask = 0b00010000;
|
||||||
|
|
||||||
|
|
@ -27,6 +89,7 @@ void latchOutput() {
|
||||||
PORTD |= latchMask;
|
PORTD |= latchMask;
|
||||||
delayMicroseconds(1);
|
delayMicroseconds(1);
|
||||||
PORTD &= ~latchMask;
|
PORTD &= ~latchMask;
|
||||||
|
delayMicroseconds(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void commitWrite() {
|
void commitWrite() {
|
||||||
|
|
@ -87,29 +150,43 @@ void setAddress(int address, bool outputEnable) {
|
||||||
latchOutput();
|
latchOutput();
|
||||||
}
|
}
|
||||||
|
|
||||||
byte readEEPROM(int address) {
|
byte readBus(int address) {
|
||||||
// TODO: Think about adding a delay if the last operation was a write and where it is appropriate to put it.
|
|
||||||
// If the last operation wasn't a read we need to set our pins as input.
|
|
||||||
if (lastOp != LAST_OP_READ) {
|
|
||||||
setBusMode(READ_MODE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// In contrast with the write function, it's okay to set output enable after setting the
|
// In contrast with the write function, it's okay to set output enable after setting the
|
||||||
// pins as inputs. This way, the arduino pins are already ready to sink current when the
|
// pins as inputs. This way, the arduino pins are already ready to sink current when the
|
||||||
// EEPROM starts driving the bus.
|
// EEPROM starts driving the bus.
|
||||||
byte result = (PINB << 3) | (PIND >> 5) ;
|
setAddress(address, true);
|
||||||
|
// For some reason, PINB takes a long time to update, a delay of a minimum of 2 microsends
|
||||||
lastOp = LAST_OP_READ;
|
// Must be added. The datasheet of the AT28C256 specifies a time from address to output of 150ns max
|
||||||
return result;
|
// and a time from output enabled to output of 70ns max, thus it makes no sense to wait 2000ns, but
|
||||||
|
// if it is not done, the most significant nibble is always 0xF.
|
||||||
|
delayMicroseconds(2);
|
||||||
|
return (PINB << 3) | (PIND >> 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
byte readEEPROM(int address) {
|
||||||
|
// If the last operation wasn't a read we need to set our pins as input
|
||||||
|
if (lastOp != LAST_OP_READ) {
|
||||||
|
setBusMode(READ_MODE);
|
||||||
|
// If last op was a write we need to poll for valid data.
|
||||||
|
if (lastOp == LAST_OP_WRITE) {
|
||||||
|
while (readBus(lastAddressWritten) != lastDataWritten);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lastOp = LAST_OP_READ;
|
||||||
|
return readBus(address);
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeEEPROM(int address, byte data, bool pollOnPageChange) {
|
||||||
|
// Since we're performing page writes, we must poll the data when we change page.
|
||||||
|
if (
|
||||||
|
((address & 0xFFC0) != (lastAddressWritten & 0xFFC0))
|
||||||
|
&& isFirstWrite == false
|
||||||
|
&& pollOnPageChange
|
||||||
|
) {
|
||||||
|
while(readEEPROM(lastAddressWritten) != lastDataWritten);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes a single byte of data to the specified address.
|
|
||||||
* If cooldown is true, the function adds a delay to avoid
|
|
||||||
* reading incorrect data after a write.
|
|
||||||
*/
|
|
||||||
void writeEEPROM(int address, byte data, bool cooldown) {
|
|
||||||
// For the write case, must turn output enable off before setting the pins as outputs.
|
// For the write case, must turn output enable off before setting the pins as outputs.
|
||||||
// If we don't do this, for a brief period of time, both the arduino and the EEPROM would
|
// If we don't do this, for a brief period of time, both the arduino and the EEPROM would
|
||||||
// drive the bus and this could case problems.
|
// drive the bus and this could case problems.
|
||||||
|
|
@ -122,37 +199,71 @@ void writeEEPROM(int address, byte data, bool cooldown) {
|
||||||
|
|
||||||
// EEPROM_D0 to D2 correspond to PD5 to PD7
|
// EEPROM_D0 to D2 correspond to PD5 to PD7
|
||||||
// EEPROM_D3 to D7 correspond to PB0 to PB4
|
// EEPROM_D3 to D7 correspond to PB0 to PB4
|
||||||
PORTD &= (data << 5) & 0b00011111;
|
PORTD = (PORTD & 0b00011111 ) | (data << 5);
|
||||||
PORTB &= (data >> 3) & 0b11100000;
|
PORTB = (PORTB & 0b11100000) | (data >> 3) ;
|
||||||
|
|
||||||
|
// Slow version.
|
||||||
|
//for (int pin = EEPROM_D0; pin < EEPROM_D7; pin++, data >>= 1) {
|
||||||
|
// digitalWrite(pin, data & 1);
|
||||||
|
//}
|
||||||
|
|
||||||
commitWrite();
|
commitWrite();
|
||||||
lastOp = LAST_OP_WRITE;
|
lastOp = LAST_OP_WRITE;
|
||||||
|
isFirstWrite = false;
|
||||||
|
|
||||||
|
lastAddressWritten = address;
|
||||||
|
lastDataWritten = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void disableSoftwareProtection() {
|
||||||
|
|
||||||
|
writeEEPROM(0x5555, 0xAA, false);
|
||||||
|
writeEEPROM(0x2AAA, 0x55, false);
|
||||||
|
writeEEPROM(0x5555, 0x80, false);
|
||||||
|
writeEEPROM(0x5555, 0xAA, false);
|
||||||
|
writeEEPROM(0x2AAA, 0x55, false);
|
||||||
|
writeEEPROM(0x5555, 0x20, false);
|
||||||
|
|
||||||
if (cooldown) {
|
|
||||||
delay(10);
|
delay(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
void erase() {
|
||||||
|
for (long addr = 0; addr < 32768; addr++) {
|
||||||
|
writeEEPROM(addr, 0xFF, true);
|
||||||
|
}
|
||||||
|
// Ack the operation.
|
||||||
|
Serial.write(0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
void program() {
|
||||||
|
// For now, the programmer will always write to the whole eeprom.
|
||||||
|
byte value;
|
||||||
|
// The program will write byte by byte.
|
||||||
|
for (long addr = 0; addr < 32768; addr++) {
|
||||||
|
// Wait for next value.
|
||||||
|
while(Serial.available() == 0);
|
||||||
|
value = Serial.read();
|
||||||
|
writeEEPROM(addr, value, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dump() {
|
||||||
|
unsigned long startAddress = 0;
|
||||||
|
unsigned long byteCount = 0;
|
||||||
|
byte value;
|
||||||
|
// Wait and read the starting address to dump.
|
||||||
|
while (Serial.available() < 2);
|
||||||
|
startAddress |= Serial.read();
|
||||||
|
startAddress |= Serial.read() << 8;
|
||||||
|
|
||||||
void setup() {
|
// Wait and read the byte count.
|
||||||
// put your setup code here, to run once:
|
while (Serial.available() < 2);
|
||||||
pinMode(SHIFT_DATA, OUTPUT);
|
byteCount |= Serial.read();
|
||||||
pinMode(SHIFT_CLK, OUTPUT);
|
byteCount |= Serial.read() << 8;
|
||||||
pinMode(SHIFT_LATCH, OUTPUT);
|
|
||||||
|
|
||||||
digitalWrite(EEPROM_WE, HIGH);
|
|
||||||
pinMode(EEPROM_WE, OUTPUT);
|
|
||||||
|
|
||||||
// Setting an invalid value.
|
|
||||||
lastOp = -1;
|
|
||||||
|
|
||||||
Serial.begin(9600);
|
|
||||||
|
|
||||||
writeEEPROM(0x1234, 0x55, true);
|
|
||||||
writeEEPROM(0x4321, 0x7E, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop() {
|
|
||||||
// put your main code here, to run repeatedly:
|
|
||||||
|
|
||||||
|
for (int address = startAddress; address < startAddress + byteCount; address++ ) {
|
||||||
|
value = readEEPROM(address);
|
||||||
|
Serial.write(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,23 @@
|
||||||
#define ADDRESS_CLOCK 18
|
#define ADDRESS_CLOCK 18
|
||||||
#define WRITE_CLOCK 19
|
#define WRITE_CLOCK 19
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
PORT mappings for data pins:
|
||||||
|
|
||||||
|
2 PORTE 4
|
||||||
|
3 PORTE 5
|
||||||
|
4 PORTG 5
|
||||||
|
5 PORTE 3
|
||||||
|
6 PORTH 3
|
||||||
|
7 PORTH 4
|
||||||
|
8 PORTH 5
|
||||||
|
9 PORTH 6
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
Serial.begin(9600);
|
Serial.begin(115200);
|
||||||
attachInterrupt(digitalPinToInterrupt(ADDRESS_CLOCK), onAddressClock, RISING);
|
attachInterrupt(digitalPinToInterrupt(ADDRESS_CLOCK), onAddressClock, RISING);
|
||||||
attachInterrupt(digitalPinToInterrupt(WRITE_CLOCK), onWriteClock, FALLING);
|
attachInterrupt(digitalPinToInterrupt(WRITE_CLOCK), onWriteClock, FALLING);
|
||||||
}
|
}
|
||||||
|
|
@ -28,9 +43,15 @@ void onAddressClock() {
|
||||||
|
|
||||||
void onWriteClock() {
|
void onWriteClock() {
|
||||||
Serial.print("Data: 0b");
|
Serial.print("Data: 0b");
|
||||||
for (int pin = DATA_7; pin >= DATA_0; pin--) {
|
// TODO: Find a way of making this more readable.
|
||||||
Serial.print(digitalRead(pin));
|
Serial.print((PINH & 0x40) >> 6);
|
||||||
}
|
Serial.print((PINH & 0x20) >> 5);
|
||||||
|
Serial.print((PINH & 0x10) >> 4);
|
||||||
|
Serial.print((PINH & 0x08) >> 3);
|
||||||
|
Serial.print((PINE & 0x08) >> 3);
|
||||||
|
Serial.print((PING & 0x20) >> 5);
|
||||||
|
Serial.print((PINE & 0x20) >> 5);
|
||||||
|
Serial.print((PINE & 0x10) >> 4);
|
||||||
Serial.println();
|
Serial.println();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
160
cli/cli.py
Normal file
160
cli/cli.py
Normal file
|
|
@ -0,0 +1,160 @@
|
||||||
|
import argparse
|
||||||
|
import time
|
||||||
|
import serial
|
||||||
|
from tqdm import tqdm
|
||||||
|
|
||||||
|
|
||||||
|
def get_parsed_args():
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
subparsers = parser.add_subparsers(title="Operation to perform", dest="operation")
|
||||||
|
|
||||||
|
program_parser = subparsers.add_parser("program")
|
||||||
|
dump_parser = subparsers.add_parser("dump")
|
||||||
|
erase_parser = subparsers.add_parser("erase")
|
||||||
|
|
||||||
|
# Parser for the "program" subcommand.
|
||||||
|
program_parser.add_argument(
|
||||||
|
"-f",
|
||||||
|
"--file",
|
||||||
|
help="Binary file containing the program",
|
||||||
|
type=argparse.FileType("rb"),
|
||||||
|
required=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
program_parser.add_argument(
|
||||||
|
"-p", "--port", help="Serial port where programmer is located", required=True
|
||||||
|
)
|
||||||
|
|
||||||
|
# Parser for the dump subcommand.
|
||||||
|
dump_parser.add_argument(
|
||||||
|
"-f",
|
||||||
|
"--file",
|
||||||
|
help="The file where the binary dump will be stored",
|
||||||
|
type=argparse.FileType("wb"),
|
||||||
|
required=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
dump_parser.add_argument(
|
||||||
|
"-p", "--port", help="Serial port where programmer is located", required=True
|
||||||
|
)
|
||||||
|
|
||||||
|
dump_parser.add_argument(
|
||||||
|
"-s",
|
||||||
|
"--start",
|
||||||
|
help="The address where to start dumping",
|
||||||
|
type=int,
|
||||||
|
required=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
dump_parser.add_argument(
|
||||||
|
"-c",
|
||||||
|
"--byte-count",
|
||||||
|
help="The amount of bytes to dump",
|
||||||
|
type=int,
|
||||||
|
required=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
dump_parser.add_argument(
|
||||||
|
"--display",
|
||||||
|
help="Print the dump to the screen after storing it to the file",
|
||||||
|
action="store_true",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Parser for the erase command .
|
||||||
|
erase_parser.add_argument(
|
||||||
|
"-p",
|
||||||
|
"--port",
|
||||||
|
help="Serial port where the programmer is located",
|
||||||
|
required=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
return parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
|
def program(args):
|
||||||
|
print("Programming...")
|
||||||
|
with serial.Serial(args.port, 115200) as ser:
|
||||||
|
# Give a chance to the arduino to reset.
|
||||||
|
# TODO: Arduino resets by default when opening a serial
|
||||||
|
# connection, there's ways to avoid this. Investigate more.
|
||||||
|
time.sleep(2)
|
||||||
|
|
||||||
|
# Sending command
|
||||||
|
ser.write((0).to_bytes(1, "big"))
|
||||||
|
|
||||||
|
bytes_to_write = args.file.read()
|
||||||
|
# Forward the bytes from the selected file
|
||||||
|
for i in tqdm(range(32 * 1024)):
|
||||||
|
value = (bytes_to_write[i]).to_bytes(1, "big")
|
||||||
|
ser.write(value)
|
||||||
|
# This delay was found by experimentation.
|
||||||
|
# A byte write in the arduino takes about 80us.
|
||||||
|
# Every 64 bytes (a page) we do data polling and could
|
||||||
|
# take much longer. A byte send given a 115200 baud rate
|
||||||
|
# should take ~70us, a 100us delay should give the EEPROM enough time
|
||||||
|
# to internally write the page withouh the UART read buffer (64 bytes)
|
||||||
|
# overflowing.
|
||||||
|
time.sleep(100.0 * 1e-6)
|
||||||
|
print("Done programming!")
|
||||||
|
|
||||||
|
|
||||||
|
def dump(args):
|
||||||
|
print("Dumping...")
|
||||||
|
with serial.Serial(args.port, 115200) as ser:
|
||||||
|
address = int(args.start)
|
||||||
|
byte_count = int(args.byte_count)
|
||||||
|
|
||||||
|
# TODO: Avoid arduino autoreset.
|
||||||
|
print("Waiting for the arduino to reset...")
|
||||||
|
time.sleep(2)
|
||||||
|
|
||||||
|
# Sending command
|
||||||
|
ser.write((1).to_bytes(1, "big"))
|
||||||
|
|
||||||
|
# Sending address, low byte first.
|
||||||
|
ser.write((address & 0xFF).to_bytes(1, "big"))
|
||||||
|
ser.write(((address & 0xFF00) >> 8).to_bytes(1, "big"))
|
||||||
|
# Sending byte count, low byte first.
|
||||||
|
ser.write((byte_count & 0xFF).to_bytes(1, "big"))
|
||||||
|
ser.write(((byte_count & 0xFF00) >> 8).to_bytes(1, "big"))
|
||||||
|
|
||||||
|
# Read the stream coming from the Arduino and forward them
|
||||||
|
# to the user-selected dump file.
|
||||||
|
for _ in range(byte_count):
|
||||||
|
args.file.write(ser.read())
|
||||||
|
print("Done dumping!")
|
||||||
|
|
||||||
|
|
||||||
|
def erase(args):
|
||||||
|
print("Erasing...")
|
||||||
|
with serial.Serial(args.port, 115200) as ser:
|
||||||
|
|
||||||
|
# TODO: Avoid arduino autoreset.
|
||||||
|
print("Waiting for the arduino to reset...")
|
||||||
|
time.sleep(2)
|
||||||
|
|
||||||
|
ser.write((2).to_bytes(1, "big"))
|
||||||
|
|
||||||
|
# Wait for the ack.
|
||||||
|
if ser.read() == b"\xFF":
|
||||||
|
print("Erasing completed!")
|
||||||
|
else:
|
||||||
|
print("Erasing failed")
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
args = get_parsed_args()
|
||||||
|
|
||||||
|
if args.operation == "program":
|
||||||
|
program(args)
|
||||||
|
elif args.operation == "dump":
|
||||||
|
dump(args)
|
||||||
|
elif args.operation == "erase":
|
||||||
|
erase(args)
|
||||||
|
else:
|
||||||
|
print("Unrecognized command, exiting now...")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
17
cli/requirements.txt
Normal file
17
cli/requirements.txt
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
appdirs==1.4.4
|
||||||
|
astroid==2.4.2
|
||||||
|
isort==5.6.4
|
||||||
|
jedi==0.17.2
|
||||||
|
lazy-object-proxy==1.4.3
|
||||||
|
mccabe==0.6.1
|
||||||
|
mypy-extensions==0.4.3
|
||||||
|
parso==0.7.1
|
||||||
|
pathspec==0.8.1
|
||||||
|
pylint==2.6.0
|
||||||
|
pyserial==3.5
|
||||||
|
rope==0.18.0
|
||||||
|
six==1.15.0
|
||||||
|
toml==0.10.2
|
||||||
|
tqdm==4.54.1
|
||||||
|
typing-extensions==3.7.4.3
|
||||||
|
wrapt==1.12.1
|
||||||
BIN
images/protoboard_assembly.JPG
Normal file
BIN
images/protoboard_assembly.JPG
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.1 MiB |
16
serial_monitor/requirements.txt
Normal file
16
serial_monitor/requirements.txt
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
appdirs==1.4.4
|
||||||
|
astroid==2.4.2
|
||||||
|
isort==5.6.4
|
||||||
|
jedi==0.17.2
|
||||||
|
lazy-object-proxy==1.4.3
|
||||||
|
mccabe==0.6.1
|
||||||
|
mypy-extensions==0.4.3
|
||||||
|
parso==0.7.1
|
||||||
|
pathspec==0.8.1
|
||||||
|
pylint==2.6.0
|
||||||
|
pyserial==3.5
|
||||||
|
rope==0.18.0
|
||||||
|
six==1.15.0
|
||||||
|
toml==0.10.2
|
||||||
|
typing-extensions==3.7.4.3
|
||||||
|
wrapt==1.12.1
|
||||||
44
serial_monitor/serial_monitor.py
Normal file
44
serial_monitor/serial_monitor.py
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
import glob
|
||||||
|
import argparse
|
||||||
|
import serial
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument("--port")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
# Get all the valid serial ports available.
|
||||||
|
available_ports = glob.glob("/dev/cu.*")
|
||||||
|
|
||||||
|
# Only do this if the user did not specify a port.
|
||||||
|
if args.port is None:
|
||||||
|
# Make the user select a port to start a listening session.
|
||||||
|
print("Available ports:")
|
||||||
|
for i, port in enumerate(available_ports):
|
||||||
|
print(f"{i} - {port}")
|
||||||
|
|
||||||
|
selected_port_index = None
|
||||||
|
while selected_port_index is None and args.port is None:
|
||||||
|
try:
|
||||||
|
selected_port_index = input(
|
||||||
|
"\nType port number to start listening section: "
|
||||||
|
)
|
||||||
|
selected_port_index = int(selected_port_index)
|
||||||
|
if selected_port_index < 0 or selected_port_index >= len(available_ports):
|
||||||
|
print("The port number you provided does not exist.")
|
||||||
|
selected_port_index = None
|
||||||
|
except:
|
||||||
|
print("The typed input is not valid, please enter a valid number.")
|
||||||
|
selected_port_index = None
|
||||||
|
|
||||||
|
port = args.port if args.port is not None else available_ports[selected_port_index]
|
||||||
|
# TODO: Allow selecting baud raute, 115200 by default for now.
|
||||||
|
with serial.Serial(port, 115200) as ser:
|
||||||
|
while True:
|
||||||
|
byte = ser.read()
|
||||||
|
print(byte.decode("utf-8"), end="")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Loading…
Add table
Add a link
Reference in a new issue