#!/bin/env /usr/bin/python
#
# Copyright 2005 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
# GNU Radio is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# GNU Radio is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GNU Radio; see the file COPYING.  If not, write to
# the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
#
# program to read prepared ifft data converted from a line of
# text, do the ifft and output repeatedly

from gnuradio import gr
from gnuradio import audio

def build_graph ():

	fft_size = 1024
	sampling_freq = 8000

	fg = gr.flow_graph()

	src = gr.file_source(gr.sizeof_short,"slout",1)
	s2f = gr.short_to_float()
	f2c = gr.float_to_complex()
	s2v = gr.stream_to_vector(gr.sizeof_gr_complex,fft_size)
	ifft = gr.fft_vcc(fft_size,False,False) # 1024, reverse, no window
	v2s = gr.vector_to_stream(gr.sizeof_gr_complex,fft_size)
	c2f = gr.complex_to_float()
	scaler = gr.multiply_const_ff(.001)
	dst = audio.sink(sampling_freq)

	fg.connect(src,s2f,f2c,s2v,ifft,v2s,c2f,scaler,dst)

	return fg

if __name__ == '__main__':

	# get character map
	ct = open("charset_6574","r") 
	charmap = ct.read()
	ct.close()

	# A line of text, fill out to 32 characters long
	tline = '  GNURadio '
	for i in range(len(tline),32):
	  tline += ' '

# the cumulative scan lines. 32 characters / line - only 16 displayed
# due to complex ifft. Each Character is 8x13 blocks, and each block is
# 4x4 bits, but height can vary depending on waterfall speed.
# Total scan line length is to be 1024 bits for a 1024 bin ifft, with
# sample rate at 8Khz that would be 7.8125 hz / bin. In the final output
# file sent to gnuradio, each ifft bin is a 2-byte 16 bit short number.

	slout = open("slout","w")       # file to save data for gnuradio
	sline = ''                      # define scan line buffer as string
# the next line depends on whether your waterfall display scrolls from the
# bottom up, like Baudline, or from the top down. If it's bottom up you want
# the characters to scan from the top down, i.e., range(0,12).  Otherwise
# you want them to scan from the bottom up, i.e., range(12,-1,-1).
	for sl in range(12,-1,-1):      # 13 scan lines
	  for ch in range(0,32):        # 32 characters / line
	      chline = charmap[ord(tline[ch])*13+sl]        
					# scan line for this character 
	      # turn 1 byte into 4,  4 bit 'blocks' for each bit
	      for chl in range(7,0,-2): # loop across bits
	        if ord(chline) & (0x01 << chl): # AND with bit mask
	          slnyb = 0xf0          # scan line hi nybble is F if bit True
	        else:
	          slnyb = 0x00          # 0 if False
	        if ord(chline) & (0x01 << chl-1):
	          slnyb += 0x0f         # lo hybble F if next bit True
	        # now turn the two scan line nybbles into 8 16bit numbers
	        for scn in range(7,-1,-1): # loop across bits
	          if slnyb & (0x01 << scn):
	            sline += chr(0x04) + chr(0x00) # this number fed to ifft
	          else:				   # two make a 16-bit short
	            sline += chr(0x00) + chr(0x00) # beware of byte swap LO+HI
# The next line varies with the speed of your waterfall display, a fast one
# like Baudline only needs a few lines of height. A slow one like psk31 Deluxe
# need very tall characters.
	  for bh in range(0,16):
	    slout.write(sline)          # save a line, several times for
					# block height
	  sline = ''			# reset scan line

	# close disk file
	slout.close()

	# Now start the ifft loop
	fg = build_graph()
	fg.start ()
	raw_input ('Press Enter to quit: ')
	fg.stop ()

