#!/usr/bin/python
# -*- coding: utf-8 -*-

import sys, os




# Define register Mnemonics
CONFIG = int("0x00", 16)
EN_AA = int("0x01", 16)
EN_RXADDR = int("0x02", 16)
SETUP_AW = int("0x03", 16)
SETUP_RETR = int("0x04", 16)
RF_CH = int("0x05", 16)
RF_SETUP = int("0x06", 16)
STATUS = int("0x07", 16)
OBSERVE_TX = int("0x08", 16)
RPD = int("0x09", 16)
RX_ADDR_P0 = int("0x0A", 16)
RX_ADDR_P1 = int("0x0B", 16)
RX_ADDR_P2 = int("0x0C", 16)
RX_ADDR_P3 = int("0x0D", 16)
RX_ADDR_P4 = int("0x0E", 16)
RX_ADDR_P5 = int("0x0F", 16)
TX_ADDR = int("0x10", 16)
RX_PW_P0 = int("0x11", 16)
RX_PW_P1 = int("0x12", 16)
RX_PW_P2 = int("0x13", 16)
RX_PW_P3 = int("0x14", 16)
RX_PW_P4 = int("0x15", 16)
RX_PW_P5 = int("0x16", 16)
FIFO_STATUS = int("0x17", 16)

# Define command Mnemonics (Instructions)
R_REGISTER = int("00000000", 2) 
W_REGISTER = int("00100000", 2)
R_RX_PAYLOAD = int("01100001", 2)
W_TX_PAYLOAD = int("10100000", 2)
FLUSH_TX = int("11100001", 2)
FLUSH_RX = int("11100010", 2)
REUSE_TX_PL = int("11100011", 2)
ACTIVATE = int("01010000", 2)
R_RX_PL_WID = int("01100000", 2)
W_ACK_PAYLOAD = int("10100000", 2)
W_TX_PAYLOAD_NO_ACK = int("10110000", 2)
NOP = int("11111111", 2)


def logEntryToHex(entry):
	entry = entry.rstrip()
	return entry[len(entry) - 5:len(entry) - 1]
	
def readLog(fileName):
	# Parses the given log file.
	# Returns a list containing tuples of the form (<time>, <MOSI>, <MISO>)
	
	logFile = open(fileName, 'r')
	
	# Input Format is: Time [s],Packet ID,MOSI,MISO
	result = []
	
	for curLine in logFile:
		#print curLine
		tokens = curLine.split(",")
		result.append((tokens[0], logEntryToHex(tokens[2]), logEntryToHex(tokens[3])))
		
	return result[1:len(result)]
		

def groupDataByTime(inputData):
	# Returns a list of groups of data. The groups are
	# composed based on temporal proximity. Adjust threshold
	# according to actual timing.
	threshold = 0.001
	
	result = []
	curGroup = []
	
	lastTime = -100.0
	
	# Iterate input data
	for curData in inputData:
		# Get informations from data word
		curTime = float(curData[0])
		timeDistance = curTime - lastTime
		
		# New group, create new group and close current
		if threshold < timeDistance:
			if len(curGroup) > 0:
				result.append(curGroup)
			curGroup = []
				
		# Append data to current group
		curGroup.append(curData)
		lastTime = curTime
		
	return result
		

def parseRegisterName(word):
	wordAdressPart = word & int("00011111", 2)
	
	if wordAdressPart == CONFIG:
		return "CONFIG"
	elif wordAdressPart == STATUS:
		return "STATUS"
	elif wordAdressPart == RF_CH:
		return "RF_CH"
	else:
		return "UNKNOWN (" + str(hex(wordAdressPart)) + ")"
		

def extractFirstCommand(group, channels, payloads):
	# Extracts informations about the first command
	# and all its parameters. 
	
	firstWord = group.pop(0)[1]
	firstWordAsInt = int(firstWord, 16)
	firstWordFirstThreeBits = firstWordAsInt & int("11100000", 2)

	#print firstWord, firstWordAsInt
	mode = ""
	
	# Check type of command word
	if firstWordAsInt == R_RX_PAYLOAD:
		print "R_RX_PAYLOAD"
	elif firstWordAsInt == W_TX_PAYLOAD:
		# Payload transmission 
		totalPayload = ""
		payloadLength = 0
		while len(group) > 0:
			nextBit = group.pop(0) 
			totalPayload = totalPayload + " " + nextBit[1]
			payloadLength = payloadLength + 1
		print "W_TX_PAYLOAD: " + str(payloadLength) + " Bit\t" + totalPayload 
		
		# Store value
		payloads.append(totalPayload)
		
	elif firstWordAsInt == FLUSH_TX:
		print "FLUSH_TX"
	elif firstWordAsInt == FLUSH_RX:
		print "FLUSH_RX"
	elif firstWordAsInt == REUSE_TX_PL:
		print "REUSE_TX_PL"
	elif firstWordAsInt == ACTIVATE:
		print "ACTIVATE"
	elif firstWordAsInt == R_RX_PL_WID:
		print "R_RX_PL_WID"
	elif firstWordAsInt == W_ACK_PAYLOAD:
		print "W_ACK_PAYLOAD"
	elif firstWordAsInt == W_TX_PAYLOAD_NO_ACK:
		print "W_TX_PAYLOAD_NO_ACK"
	elif firstWordAsInt == NOP:
		print "NOP"		
	elif firstWordFirstThreeBits == R_REGISTER:
		print "R_REGISTER: " + parseRegisterName(firstWordAsInt)
	elif firstWordFirstThreeBits == W_REGISTER:
		# Fetch value that will be written
		if len(group) > 0:
			newRegisterValue = int(group.pop(0)[1], 16)
			newRegisterValueAsBin = bin(newRegisterValue)
			registerName = parseRegisterName(firstWordAsInt)
			print "W_REGISTER: " + registerName + " \t " + str(newRegisterValueAsBin) 
			if registerName == "RF_CH":
				channels.append(newRegisterValue)	
		else:
			print "Error! W_REGISTER without data!"
	else:
		print "UNKNOWN (" + firstWord + ")" 
		
	
def writeListToFile(listContent, fileName):
	outFile = open(fileName, 'w')
	
	for curLine in listContent:
		outFile.write(str(curLine) + "\n")
	
	outFile.close()
		
def printList(listContent, title):
	print ""
	print ""
	print "##################################"
	print title
	print "##################################"			
	print listContent

		
	
if __name__ == '__main__':
	if len(sys.argv) < 4:
		print "Error. Too few command line arguments."
		print "Please call parseSPI.pi <SPI-Trace> <Channel Target File> <Payload Target File>"
	else:
		# First read and parse log file
		logData = readLog(sys.argv[1])
		
		# Group data according to their temporal proximity
		dataGroups = groupDataByTime(logData)

		# Process groups
		channels = []
		payloads = []
		for curGroup in dataGroups:
			print ""
			print ""
			print "##################################"
			print "New Packet, Data Word Count: " + str(len(curGroup))
			print "##################################"

			while len(curGroup) > 0:
				extractFirstCommand(curGroup, channels, payloads)
		print ""
		print ""
				
		# Save channels and payloads as file or output on screen
		if len(sys.argv) > 3:
			writeListToFile(channels, sys.argv[2])
			writeListToFile(payloads, sys.argv[3])
		else:
			printList(payloads, "All Payloads")
			printList(channels, "All Channels")
			
			
		