diff --git a/firmware/scripts/sstv_test.py b/firmware/scripts/sstv_test.py new file mode 100644 index 0000000..dedf0dd --- /dev/null +++ b/firmware/scripts/sstv_test.py @@ -0,0 +1,120 @@ +#/usr/bin/env python3 +import numpy as np + + +from scipy.io import wavfile +from scipy.misc import imread +from matplotlib import pyplot as plt + + +WIDTH = 640 +HEIGHT = 496 + +OUTPUT_RATE = 48000 + +VIS_START_FREQ = 1900 +VIS_START_DUR = 300 +VIS_PAUSE = 10 +VIS_ONE_FREQ = 1100 +VIS_ZERO_FREQ = 1300 +VIS_BIT_DUR = 30 +# Code 97 + even parity, lsb first +VIS_BITS = [True, False, False, False, False, True, True, True] + +SYNC_FREQ = 1200 +SYNC_DUR = 20 + +PORCH_DUR = 2.080 + +PIXEL_DUR = 0.382 + +COLOR_LOW_FREQ = 1500 +COLOR_HIGH_FREG = 2300 + +phase_acc = 0 + + +def sine_gen(freq): + global phase_acc + phase_inc = (2 * np.pi / OUTPUT_RATE) * freq + phase_acc += phase_inc + if phase_acc > 2 * np.pi: + phase_acc = phase_acc - 2 * np.pi + + return np.sin(phase_acc) + + +samples_left = 0 +def make_tone(freq, duration, data): + global samples_left + samples = duration / 1000 * OUTPUT_RATE + samples_left + sample_count = int(samples) + samples_left = samples - sample_count + + for i in range(0, sample_count): + data += [sine_gen(freq)] + + + + +def make_vis(samples): + make_tone(VIS_START_FREQ, VIS_START_DUR, samples) + make_tone(SYNC_FREQ, VIS_PAUSE, samples) + make_tone(VIS_START_FREQ, VIS_START_DUR, samples) + + make_tone(SYNC_FREQ, VIS_BIT_DUR, samples) + for bit in VIS_BITS: + if bit: + make_tone(VIS_ONE_FREQ, VIS_BIT_DUR, samples) + else: + make_tone(VIS_ZERO_FREQ, VIS_BIT_DUR, samples) + + make_tone(SYNC_FREQ, VIS_BIT_DUR, samples) + + +def main(): + + image = imread('testcard.png', mode='YCbCr') + + samples = [] + + make_vis(samples) + + for y in range(0, int(HEIGHT/2)): + make_tone(SYNC_FREQ, SYNC_DUR, samples) + make_tone(COLOR_LOW_FREQ, PORCH_DUR, samples) + + for x in range(0, WIDTH): + lum = image[y*2, x, 0] / 255.0 + freq = COLOR_LOW_FREQ + lum * (COLOR_HIGH_FREG - COLOR_LOW_FREQ) + make_tone(freq, PIXEL_DUR, samples) + + for x in range(0, WIDTH): + cr0 = image[y*2, x, 2] / 255.0 + cr1 = image[y*2 + 1, x, 2] / 255.0 + cr = (cr0 + cr1) / 2 + freq = COLOR_LOW_FREQ + cr * (COLOR_HIGH_FREG - COLOR_LOW_FREQ) + make_tone(freq, PIXEL_DUR, samples) + + for x in range(0, WIDTH): + cb0 = image[y*2, x, 1] / 255.0 + cb1 = image[y*2 + 1, x, 1] / 255.0 + cb = (cb0 + cb1) / 2 + freq = COLOR_LOW_FREQ + cb * (COLOR_HIGH_FREG - COLOR_LOW_FREQ) + make_tone(freq, PIXEL_DUR, samples) + + for x in range(0, WIDTH): + lum = image[y*2 + 1, x, 0] / 255.0 + freq = COLOR_LOW_FREQ + lum * (COLOR_HIGH_FREG - COLOR_LOW_FREQ) + make_tone(freq, PIXEL_DUR, samples) + + + samples = np.array(samples) + + samples = samples * 0.75 * 32767 + samples = np.int16(samples) + + wavfile.write("output.wav", OUTPUT_RATE, samples) + +if __name__ == '__main__': + main() diff --git a/firmware/scripts/testcard.png b/firmware/scripts/testcard.png new file mode 100644 index 0000000..a0cce5a Binary files /dev/null and b/firmware/scripts/testcard.png differ