summaryrefslogtreecommitdiff
path: root/utilities/blinkenrocket.py
diff options
context:
space:
mode:
authorSebastian Muszytowski <sebastian@muszytowski.net>2016-01-27 22:06:03 +0100
committerSebastian Muszytowski <sebastian@muszytowski.net>2016-01-27 22:06:03 +0100
commitb07679771f1c59ed623ae5ad7f7baff5b0ba9b9e (patch)
tree3cd2aefa10060eb7ed066cbcdc6fa19716b4611c /utilities/blinkenrocket.py
parent420cb4b1b01166739d57d37c3b95e6b6391555d7 (diff)
removed obsolete code, added new blinkenrocket python suite
Diffstat (limited to 'utilities/blinkenrocket.py')
-rw-r--r--utilities/blinkenrocket.py176
1 files changed, 176 insertions, 0 deletions
diff --git a/utilities/blinkenrocket.py b/utilities/blinkenrocket.py
new file mode 100644
index 0000000..6dc3ea6
--- /dev/null
+++ b/utilities/blinkenrocket.py
@@ -0,0 +1,176 @@
+#!/usr/bin/env python
+
+import sys, wave
+
+class modem:
+
+ # Modem specific constants
+ bits = [[3 * chr(0), 5 * chr(0)], [3 * chr(255), 5 * chr(255)]]
+ sync = [17 * chr(0), 17 * chr(255)]
+ # Variable to alternate high and low
+ hilo = 0
+ supportedFrequencies = [16000,22050,24000,32000,44100,48000]
+ cnt = 0
+ # Data variables
+ data = []
+ parity = True
+ frequency = 48000
+
+ # Hamming code translation table
+ _hammingCalculateParityLowNibble = [0, 3, 5, 6, 6, 5, 3, 0, 7, 4, 2, 1, 1, 2, 4, 7]
+ _hammingCalculateParityHighNibble = [0, 9, 10, 3, 11, 2, 1, 8, 12, 5, 6, 15, 7, 14, 13, 4]
+
+ # Almost nothing here
+ def __init__(self, data=[], parity=True, frequency=48000):
+ self.data = data
+ self.parity = parity
+ self.frequency = frequency if frequency in self.supportedFrequencies else 48000
+
+ # Calculate Hamming parity for 12,8 code (12 bit of which 8bit data)
+ def hammingCalculateParity128(self, byte):
+ return self._hammingCalculateParityLowNibble[byte&0x0F] ^ self._hammingCalculateParityHighNibble[byte >> 4]
+
+ # Calculate Hamming parity for 24,16 code (24 bit of which 16 bit are data)
+ def hammingCalculateParity2416(self, first, second):
+ return self.hammingCalculateParity128(second) << 4 | self.hammingCalculateParity128(first)
+
+ # Generate one sync-pulse
+ def syncsignal(self):
+ self.hilo ^= 1
+ return self.sync[self.hilo]
+
+ # Generate a number of sync signals
+ def generateSyncSignal(self, number):
+ sound = ""
+ for i in xrange(number):
+ sound += self.syncsignal()
+ return sound
+
+ # Decode bits to modem signals
+ def modemcode(self, byte):
+ bleep = ""
+ for x in xrange(8):
+ self.hilo ^= 1
+ bleep += self.bits[self.hilo][byte & 0x01]
+ byte >>= 1
+ return bleep
+
+ # Return <length> samples of silence
+ def silence(self, length):
+ return chr(127) * length
+
+ # Set data for modem code
+ def setData(self, data):
+ self.data = data
+
+ # Set whether to use parity or not
+ def setParity(self, parity):
+ self.parity = parity
+
+ # Set the frequency for the audio
+ def setFrequency(self, frequency):
+ self.frequency = frequency if frequency in self.supportedFrequencies else 48000
+
+ # Generates the audio frames based on the data
+ def generateAudioFrames(self):
+ if self.parity:
+ tmpdata = []
+ # for uneven length data, we have to append a null byte
+ if not len(self.data) % 2 == 0:
+ self.data.append(ord(0))
+ # insert the parity information every two bytes, sorry for the heavy casting
+ for index in range(0, len(self.data), 2):
+ tmpdata.extend(self.data[index:index+2])
+ tmpdata.append(chr(self.hammingCalculateParity2416(ord(self.data[index]),ord(self.data[index+1]))))
+ self.data = tmpdata
+ # generate the audio itself
+ # add some sync signal in front
+ sound = self.generateSyncSignal(4)
+ # process the data and insert sync signal every 10 bytes
+ for byte in self.data:
+ sound += self.modemcode(ord(byte))
+ self.cnt += 1
+ if self.cnt == 10:
+ sound += m.generateSyncSignal(2)
+ self.cnt = 0
+ # add some sync signals in the end
+ sound += m.generateSyncSignal(4)
+ return sound
+
+ def saveAudio(self,filename):
+ wav = wave.open(filename, 'wb')
+ wav.setparams((1, 1, self.frequency, 0, "NONE", None))
+ wav.writeframes(self.generateAudioFrames())
+ wav.close()
+
+class textFrame():
+ text = ""
+ speed = 0
+ delay = 0
+ direction = 0
+
+ def __init__(self,text,speed=1,delay=0,direction=0):
+ self.text = text
+ self.setSpeed(speed)
+ self.setDelay(delay)
+ self.setDirection(direction)
+
+ def setSpeed(self,speed):
+ self.speed = speed if speed < 16 else 1
+
+ def setDelay(self,delay):
+ self.delay = delay if delay < 16 else 0
+
+ def setDirection(self,direction):
+ self.direction = direction if direction in [0,1] else 0
+
+ # Header -> 4bit speed, 4 bit delay, 4 bit direction, 4 bit zero
+ def getHeader(self):
+ return [chr(self.speed << 4 | self.delay), chr(self.direction << 4 | 0x00)]
+
+ def getRepresentation(self):
+ return self.getHeader().append(list(self.text))
+
+class animationFrame():
+ animation = []
+ speed = 0
+ delay = 0
+
+ def __init__(self,animation,speed=1,delay=0):
+ self.setAnimation(animation)
+ self.setSpeed(speed)
+ self.setDelay(delay)
+
+ def setAnimation(self,animation):
+ if len(animation) % 8 is not 0:
+ raise Exception
+ else:
+ self.animation = animation
+
+ def setSpeed(self,speed):
+ self.speed = speed if speed < 16 else 1
+
+ def setDelay(self,delay):
+ self.delay = delay if delay < 16 else 0
+
+ # Header -> 4bit zero, 4bit speed, 4 bit zero, 4 bit direction
+ def getHeader(self):
+ return [self.speed, self.delay]
+
+ def getRepresentation(self):
+ return self.getHeader().extend(self.animation)
+
+class blinkenrocket():
+
+ eeprom_size = 65536
+
+ def __init__(self,eeprom_size=65536):
+ pass
+
+
+if __name__ == '__main__':
+ m = modem()
+ m.setData(['M','U','Z','Y'])
+ print m.generateAudioFrames()
+
+