-
-
Save jmpinit/5fdc73f9f54c3155681a95afe67f29cd to your computer and use it in GitHub Desktop.
Loads a Saleaa logic analyzer dump CSV made from the signals of the LCD in the Brother PE-150 embroidery machine and turns it into an image file
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| import csv | |
| import argparse | |
| from PIL import Image | |
| def main(): | |
| parser = argparse.ArgumentParser(description='Reconstruct 240x64 LCD image from logic analyzer CSV.') | |
| parser.add_argument('--input', required=True, help='Path to input CSV file') | |
| parser.add_argument('--output', required=True, help='Output image file (e.g. output.png)') | |
| args = parser.parse_args() | |
| WIDTH = 240 | |
| HEIGHT = 64 | |
| # We'll store the final image data as a 2D list of bits (0/1) | |
| image_data = [[0]*WIDTH for _ in range(HEIGHT)] | |
| # We know the sequence should contain data for 64 rows. | |
| # We'll detect the first row when we see LOAD_ROW_CLK with DIO1=1. | |
| current_row_bits = [] | |
| row_index = None # Unknown until first LOAD event with DIO1=1 | |
| rows_collected = 0 | |
| # Track previous states to detect edges | |
| prev_clk = None | |
| prev_load = None | |
| # Open and read CSV | |
| with open(args.input, 'r', newline='') as f: | |
| reader = csv.reader(f) | |
| header = next(reader) | |
| # Expect header: Time [s],SDI,DIO1,LOAD_ROW_CLK,CLK | |
| # We will index: 0:time,1:SDI,2:DIO1,3:LOAD,4:CLK | |
| for line in reader: | |
| if len(line) < 5: | |
| continue | |
| # Parse signals | |
| # time = float(line[0]) # not needed | |
| SDI = int(line[1]) | |
| DIO1 = int(line[2]) | |
| LOAD = int(line[3]) | |
| CLK = int(line[4]) | |
| # Detect edges: | |
| # Falling edge: previous=1 current=0 | |
| if prev_clk is not None: | |
| clk_falling = (prev_clk == 1 and CLK == 0) | |
| else: | |
| clk_falling = False | |
| if prev_load is not None: | |
| load_falling = (prev_load == 1 and LOAD == 0) | |
| else: | |
| load_falling = False | |
| # On falling edge of CLK, latch SDI bit | |
| if clk_falling: | |
| current_row_bits.append(SDI) | |
| # If we have collected a full row of 240 bits and we see LOAD falling edge | |
| # that finalizes one row | |
| if len(current_row_bits) == WIDTH: | |
| # Determine row index | |
| if row_index is None: | |
| # First LOAD event sets row_index=0 if DIO1=1 | |
| if DIO1 == 1: | |
| row_index = 0 | |
| else: | |
| # If we never saw first row with DIO1=1, this might be a corrupted capture | |
| # but let's assume row_index=0 anyway | |
| row_index = 0 | |
| else: | |
| # Subsequent LOAD events increment row index | |
| if DIO1 == 0: | |
| row_index += 1 | |
| else: | |
| # If DIO1=1 again at another load event, it might indicate a reset? | |
| # Just handle gracefully | |
| row_index = 0 | |
| # Store the collected bits into image_data | |
| # current_row_bits is a list of 0/1. Each corresponds to a pixel in the row. | |
| # The number of rows collected must not exceed 64 | |
| if 0 <= row_index < HEIGHT: | |
| for x, bit in enumerate(current_row_bits): | |
| image_data[row_index][x] = 1 - bit | |
| # Reset for next row | |
| current_row_bits = [] | |
| rows_collected += 1 | |
| if rows_collected >= HEIGHT: | |
| # We have all rows needed | |
| break | |
| prev_clk = CLK | |
| prev_load = LOAD | |
| # If we didn't fully get 64 rows, we still output what we have. | |
| # Convert image_data to a Pillow Image | |
| # Mode '1' is a 1-bit image. We'll assume bit=1 means white and bit=0 means black. | |
| img = Image.new('1', (WIDTH, HEIGHT)) | |
| # Pillow expects 0=black,1=white in '1' mode. | |
| # We directly set pixels: | |
| pixels = img.load() | |
| for y in range(HEIGHT): | |
| for x in range(WIDTH): | |
| # If you want to invert colors, use 1 - image_data[y][x]. | |
| pixels[x, y] = image_data[y][x] | |
| img.save(args.output) | |
| print(f'Saved reconstructed image to {args.output}') | |
| if __name__ == '__main__': | |
| main() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment