Browse Source

PASS1-139: Implement code to allow OCD to capture a screenshot over JTAG

PASS1-139
Ken Carpenter 4 years ago
parent
commit
3dada5150c
  1. 41
      ports/stm32/Justfile
  2. 14
      ports/stm32/boards/Passport/modfoundation.c
  3. 4
      ports/stm32/boards/Passport/modules/display.py
  4. 2
      ports/stm32/boards/Passport/modules/sram4.py

41
ports/stm32/Justfile

@ -55,6 +55,9 @@ clean:
run-ocd-command command:
sudo /usr/local/bin/openocd -f stlink.cfg -c "adapter speed 1000; transport select hla_swd" -f stm32h7x.cfg -c "init; reset halt; {{command}}" -c "exit"
run-ocd-command-no-halt command:
sudo /usr/local/bin/openocd -f stlink.cfg -c "adapter speed 1000; transport select hla_swd" -f stm32h7x.cfg -c "init; {{command}}" -c "exit"
# Build all Python graphics
graphics-py:
just -f boards/Passport/graphics/py/Justfile build
@ -127,3 +130,41 @@ fmt-c:
# Format the project's source code under boards/Passport
fmt: fmt-py fmt-c
# Convert a raw pixel map to a PNG
convert-screenshot from_file to_file:
#!/usr/bin/python3
from PIL import Image, ImageOps
raw_bits = open('{{from_file}}', 'rb').read()
WIDTH = 230
HEIGHT = 303
SCAN_WIDTH = 240
# Convert
img = Image.frombuffer('1', (SCAN_WIDTH, HEIGHT), raw_bits)
# Crop to actual width (framebuffer is 240 vs 230 for actual display)
img = img.crop((0, 0, WIDTH, HEIGHT))
# Invert since raw image is actually white on black - have to convert to grayscale first since invert() doesn't work
# for 1-bit per pixel black/white images.
img = ImageOps.grayscale(img)
img = ImageOps.invert(img)
# Apply a color shift to make it look nicer
img = ImageOps.colorize(img, (0,0,0,0), '#E0E0E0')
img.save('{{to_file}}')
# Capture a screenshot from Passport via OCD
screenshot filename:
#!/usr/bin/env bash
ADDR_FILE=screenshot-addr.tmp
TMP_FILE=screenshot.tmp
just run-ocd-command-no-halt "dump_image $ADDR_FILE 0x38006920 4"
N=`head -c 4 $ADDR_FILE | od -An --endian=little -t u4`
FRAMEBUFFER_ADDR=`printf '%x\n' $N`
echo FRAMEBUFFER_ADDR=$FRAMEBUFFER_ADDR
just run-ocd-command-no-halt "dump_image screenshot.tmp 0x$FRAMEBUFFER_ADDR 9090"
just convert-screenshot $TMP_FILE {{filename}}
rm -f $TMP_FILE $ADDR_FILE

14
ports/stm32/boards/Passport/modfoundation.c

@ -205,6 +205,8 @@ const mp_obj_type_t keypad_type = {
/*=============================================================================
* Start of LCD class
*=============================================================================*/
#define FRAMEBUFFER_ADDR_SRAM4 0x38006920 // NOTE: If SRAM4 layout changes, this must change too!
void
lcd_obj_print(const mp_print_t* print, mp_obj_t self_in, mp_print_kind_t kind)
{
@ -224,6 +226,18 @@ lcd_obj_make_new(const mp_obj_type_t* type, size_t n_args, size_t n_kw, const mp
lcd->base.type = &lcd_type;
lcd->spi = &spi_obj[0];
// lcd_init(false);
// If a framebuffer address was passed, save it to a known location
if (n_args == 1) {
// Get the buffer info from the passed in object
mp_buffer_info_t framebuffer_info;
mp_get_buffer_raise(args[0], &framebuffer_info, MP_BUFFER_READ);
// Save the actual address
uint32_t* framebuffer_addr = (uint32_t*)FRAMEBUFFER_ADDR_SRAM4;
*framebuffer_addr = (uint32_t)(framebuffer_info.buf);
}
return MP_OBJ_FROM_PTR(lcd);
}

4
ports/stm32/boards/Passport/modules/display.py

@ -42,11 +42,11 @@ class Display:
def __init__(self):
# Setup frame buffer, in show we will call scrn.update(self.dis) to show the buffer
self.scrn = LCD()
self.dis = framebuf.FrameBuffer(bytearray(
self.LINE_SIZE_BYTES * self.HEIGHT), self.FB_WIDTH, self.HEIGHT, framebuf.MONO_HLSB)
self.scrn = LCD(self.dis)
self.backlight = Backlight()
self.clear()

2
ports/stm32/boards/Passport/modules/sram4.py

@ -36,5 +36,7 @@ flash_cache_buf = _alloc(16 * 1024)
tmp_buf = _alloc(1024)
psbt_tmp256 = _alloc(256)
viewfinder_buf = _alloc((VIEWFINDER_WIDTH*VIEWFINDER_HEIGHT) // 8)
framebuffer_addr = _alloc(4) # Address of the frmebuffer memory so we can read it from OCD
assert _start <= SRAM4_END

Loading…
Cancel
Save