57 lines
1.7 KiB
Python
57 lines
1.7 KiB
Python
import numpy as np
|
|
import sys
|
|
|
|
# Character Set and coding
|
|
ALPHABET = (
|
|
list('abcdefghijklmnopqrstuvwxyz') +
|
|
list('ABCDEFGHIJKLMNOPQRSTUVWXYZ') +
|
|
list('0123456789') +
|
|
[' ', '.']
|
|
)
|
|
|
|
def get_hadamard(n):
|
|
assert (n & (n - 1) == 0), "Hadamard order must be power of 2"
|
|
H = np.array([[1]])
|
|
while H.shape[0] < n:
|
|
H = np.block([
|
|
[ H, H],
|
|
[ H, -H]
|
|
])
|
|
return H
|
|
|
|
def encode_message(msg, alphabet=ALPHABET):
|
|
msg = msg.strip()
|
|
if len(msg) != 40:
|
|
raise Exception("Message must be exactly 40 characters!")
|
|
# Get Hadamard codes
|
|
H = get_hadamard(64)
|
|
code_length = 64
|
|
# Normalize so signal energy stays bounded
|
|
# Each row has norm sqrt(64) = 8, so scale down by 1/8
|
|
scale = 1 / np.sqrt(code_length)
|
|
signals = []
|
|
for c in msg:
|
|
idx = alphabet.index(c)
|
|
signals.append(H[idx] * scale)
|
|
signal = np.concatenate(signals)
|
|
# Energy check (should be << 2000)
|
|
assert signal.shape[0] == 2560
|
|
energy = np.sum(signal ** 2)
|
|
if energy > 2000:
|
|
raise Exception("Signal energy above allowed!")
|
|
return signal
|
|
|
|
def main():
|
|
import argparse
|
|
parser = argparse.ArgumentParser(description="Message to signal encoder for PDC Project")
|
|
parser.add_argument('--message_file', type=str, required=True, help="Text file with exactly 40 chars.")
|
|
parser.add_argument('--output_file', type=str, required=True, help="Output signal file for client.py.")
|
|
args = parser.parse_args()
|
|
|
|
with open(args.message_file, 'r') as f:
|
|
msg = f.read().strip()
|
|
x = encode_message(msg)
|
|
np.savetxt(args.output_file, x)
|
|
|
|
if __name__ == '__main__':
|
|
main()
|