#!   /usr/bin/env   python
#    coding: utf8

# Copyright CERN, 2011
# Author: Samuel Iglesias Gonsalvez <siglesia@cern.ch>
# Licence: GPL v2 or later.
# Website: http://www.ohwr.org

import sys
import rr
import time
import os
import serial
from ptsexcept import *
from multiprocessing import Process

"""
test11: Access to the USB UART.
"""

class USB_UART:
    STAT_REG = 0x0;
    BAUD_REG = 0x4;
    TX_REG = 0x8;
    RX_REG = 0xc;
    CLK_FREQ = 50000000;

    def __init__ (self, gennum, base, base_reset, baud):
        self.bus = gennum;
	self.base = base;
	self.base_reset = base_reset;
	self.baud = baud;
	
	self.reset();
	self.setup_baud_rate(self.calculate_baud_rate(baud));

    def calculate_baud_rate(self, baud):
	return ((((baud*8) << (16 -7))+(self.CLK_FREQ >> 8))/(self.CLK_FREQ>>7))

    def reset(self):
	"""Resets the UART core to initialize the Baud counter """
	self.bus.iwrite(0,self.base_reset,4,0);
	self.bus.iwrite(0,self.base_reset,4,1);
	
    def read_ready(self):
	return ((self.bus.iread(0, self.base + self.STAT_REG, 4) & 0x2) >> 1)

    def read(self):
	return self.bus.iread(0, self.base + self.RX_REG, 4)
             
    def send(self,data):
	self.bus.iwrite(0, self.base + self.TX_REG, 4, data)
	while(self.bus.iread(0, self.base + self.STAT_REG, 4) & 0x1) :
		pass;

    def setup_baud_rate(self, baud):
	self.bus.iwrite(0, self.base + self.BAUD_REG, 4, baud)


def rx_thread(ser):

    char1 = ser.read(1);

    if (char1 != "A") :
	raise PtsError("UART sent 'A'. USB received: "+ char1)
    print "UART sent 'A'. USB received: " + char1


def main (default_directory='.'):

    path_fpga_loader = '../firmwares/fpga_loader';
    path_firmware = '../firmwares/test11.bin';
    	
    firmware_loader = os.path.join(default_directory, path_fpga_loader)
    bitstream = os.path.join(default_directory, path_firmware)
    os.system( firmware_loader + ' ' + bitstream)

    time.sleep(2);

    gennum = rr.Gennum();
    uart = USB_UART(gennum, 0x40000, 0x80000,9600)
    ser = serial.Serial(port='/dev/ttyUSB0', baudrate=9600, timeout=5);

    
    # Send using the serial port of the computer and receive using UART.
    ser.write('a')
    
    while(uart.read_ready() == 0) :
	pass

    char1 = uart.read();

    if (chr(char1) != 'a') :
	raise PtsError("USB sent 'a'. UART received: "+ chr(char1))

    print "USB sent 'a'. UART Received: " + chr(char1);
    
    # Send using UART and receiving data in the serial port of the PC.
    p = Process(target=rx_thread, args=(ser,));
    p.start();
 
    time.sleep(1.0)
    uart.send(65);

    p.join()
    ser.close()


if __name__ == '__main__' :
	main();
