#!/usr/bin/ruby
require './datawriter.rb'

#ord does not exist in Ruby 1.8.7
if not ("joo".methods.map {|i| i.to_s}).include? 'ord'
	class String
		def ord
			self[0].to_i
		end
	end
end

def calculateImplantAcceleration(highByte, lowByte)
	acceleration = highByte * 256 + lowByte
	if(acceleration & 2048 == 0)
		acceleration *= 4
	else
		acceleration = -4 * (4096 - acceleration)
	end
	return acceleration
end

def calculateCollarAcceleration(highByte, lowByte)
	calculateImplantAcceleration(highByte, lowByte)
end

def calculateImplantTemperature(highByte, lowByte)
	temperature = highByte * 256 + lowByte
	if(temperature < 2048)
		temperature *= 0.0625
	else
		temperature = -0.0625 * (4096 - temperature)
	end
	return temperature
end

def calculateCollarTemperature(highByte, lowByte)
	calculateImplantTemperature(highByte, lowByte)
end

if ARGV.length < 1
	puts "Usage: ./rem2csv.rb remfile [outputdir]"
	puts "Note: default output directory is ."
	exit
end


f = File.new(ARGV[0], 'rb')
data = DataWriter.new(ARGV[1] || '.')

while (not (f.eof?))# and f.pos < 3000)
	highByte = f.read(1).ord
	indicator = highByte & 240
	highByte = highByte & 15

	case(indicator)
		when 224 #intervals
			data.flush
			interval = Array.new(5) {
#			implantAxisInterval, implantBatteryInterval, implantTemperatureInterval, collarAxisInterval, ecgInterval = Array.new(5) {
				b1 = f.read(1).ord
				b2 = f.read(1).ord
				(b1 * 256.0 + b2) / (4096)# * 24 * 3600)
			}
			data.interval['implantAcceleration'] = interval[0]
			data.interval['collarBattery'] = data.interval['implantBattery'] = interval[1]
			data.interval['collarTemperature'] = data.interval['implantTemperature'] = interval[2]
			data.interval['collarAcceleration'] = interval[3]
			data.interval['ecg'] = interval[4]
#			collarBatteryInterval = implantBatteryInterval
#			collarTemperatureInterval = implantTemperatureInterval
			f.read(1).ord
			puts "read intervals"
			puts data.interval.inspect
#			puts ([implantAxisInterval, implantBatteryInterval, implantTemperatureInterval, collarAxisInterval, ecgInterval].map {|i| "#{(1.0/i/86400).to_s[0..5]} times/s"}).join ', '

		when 0 #ecg
			lowByte = f.read(1).ord
			data.buffer['ecg'] << (highByte * 256 + lowByte) * 0.0005
			puts "read ecg"

		when 16 #implant, x-axis
			lowByte = f.read(1).ord
			data.buffer['implantAcceleration'][0].push calculateImplantAcceleration(highByte, lowByte)
			puts "read imp.x"
		
		when 32 #implant, y-axis
			lowByte = f.read(1).ord
			data.buffer['implantAcceleration'][1].push calculateImplantAcceleration(highByte, lowByte)
			puts "read imp.y"
		
		when 48
			lowByte = f.read(1).ord
			data.buffer['implantAcceleration'][2].push calculateImplantAcceleration(highByte, lowByte)
			puts "read imp.z"
		
		when 80 #collar, x-axis
			lowByte = f.read(1).ord
			data.buffer['collarAcceleration'][0].push calculateImplantAcceleration(highByte, lowByte)
			puts "read col.x"
			
		when 96 #collar, y-axis
			lowByte = f.read(1).ord
			data.buffer['collarAcceleration'][1].push calculateImplantAcceleration(highByte, lowByte)
			puts "read col.y"
			
		when 112 #collar, z-axis
			lowByte = f.read(1).ord
			data.buffer['collarAcceleration'][2].push calculateImplantAcceleration(highByte, lowByte)
			puts "read col.z"
		
		when 144 #implant battery voltage
			lowByte = f.read(1).ord
			data.buffer['implantBattery'] << (highByte * 256 + lowByte) * 0.001
			puts "read imp.battery"
		
		when 160 #collar battery voltage
			lowByte = f.read(1).ord
			data.buffer['collarBattery'] << (highByte * 256 + lowByte) * 2.87 * 3 / 4096
			puts "read col.battery"
		
		when 64 #implant temperature
			lowByte = f.read(1).ord
			data.buffer['implantTemperature'] << calculateImplantTemperature(highByte, lowByte)
			puts "read imp.temp"
		
		when 128 #collar temperature
			lowByte = f.read(1).ord
			data.buffer['collarTemperature'] << calculateCollarTemperature(highByte, lowByte)
			puts "read col.temp"
		
		when 192 #time sync
			hour, minute, second, day, month, b1, b2 = Array.new(7) {
				f.read(1).ord
			}
			year = b1 * 256 + b2
			time = Time.mktime(year, month, day, hour, minute, second)
			data.setTime time
			puts "Time is #{time}"
		
		when 208
			lowByte = f.read(1).ord
			missingBytes = highByte * 256 + lowByte
			puts "Missing #{missingBytes} bytes"
		
		else
			puts "Unknown indicator #{indicator}, bye!"
			exit
	end
end

data.flush
