Communicating with PSP remote through serial port

Discuss using and improving Lua and the Lua Player specific to the PSP.

Moderators: Shine, Insert_witty_name

Post Reply
toddz
Posts: 5
Joined: Mon Jun 06, 2005 9:47 am

Communicating with PSP remote through serial port

Post by toddz »

I have been trying to code up some SIO port functions to deal with the PSP remote control. I have run into some problems in trying to do so and I am starting to wonder if it can be done with only the init, write, and read commands that LUA provides. I am pretty sure that I have to sequencing correct, but the remote seems to be sending the some block of bytes over and over again. It almost seems like the serial read buffer gets stuck or something. If anyone else has tried this I would be interested in sharing code.

Todd
toddz
Posts: 5
Joined: Mon Jun 06, 2005 9:47 am

Post by toddz »

Well, I thought that I may as well post the code to see if anyone wants to take a shot at it. It isn' t the best, but I think that it is pretty solid for what it is supposed to do. The only real thing missing is the fact that right now it is only setup to send a single message to the remote but that is enough for testing and it doesn't even get that far anyway.

Todd

Code: Select all

-- PSP remote control test code for SIO port

sio_buffin = ""
sio_buffout = ""
sio_bytein = nil
sio_byteout = nil
sio_index = 0
sio_phase = nil

-- remote presence variables
-- remote = 0 : remote is missing
-- remote = 1 : remote is missing, user informed
-- remote = 2 : remote is present
-- remote = 3 : remote is present, user informed

sio_remote = 0
sio_reset = 0

sio_rts = 0
sio_cts = 0
sio_countF0 = 0
sio_rxmsgs = 0
sio_txmsgs = 0

time = 0
sio_time = 0
sio_timep = 0

ping = 0

-- different print positions for header and actual data
terminalHeadX = 0
terminalHeadY = 0
terminalX = 0
terminalY = 3

green = Color.new(0, 255, 0)
blue = Color.new(0, 0, 255)
black = Color.new(0, 0, 0)
terminal = Image.createEmpty(480, 272)

function scroll(image, dx, dy)
	new = Image.createEmpty(image:width(), image:height())
	new:blit(dx, dy, image)
	return new
end

function terminalMaxY()
	if terminalY >= 31 then
		terminalY = 30
		terminal = scroll(terminal, 0, -24)
	end
end

function UpdateScreen()
	screen:blit(0, 0, terminal, 0, 0, terminal:width(), terminal:height(), false)
	screen.waitVblankStart()
	screen:flip()
end

function printTerminal(text, color)
	if color == nil then
		color = green
	end
	for index_j = 1, string.len(text) do
		char = string.sub(text, index_j, index_j)
		if char == "\n" then
			terminalHeadY = terminalHeadY + 1
			terminalHeadX = 0
		else
			terminal:print(terminalHeadX * 8, terminalHeadY * 8, char, color)
			terminalHeadX = terminalHeadX + 1
			if terminalHeadX >= 60 then
				terminalHeadX = 0
				terminalHeadY = terminalHeadY + 1
			end
		end
	end
end

function normalizeLinefeed(text)
	-- terminal programs like Hyperterminal sends just a \r for return key, convert it
	result = ""
	for index_k = 1, string.len(text) do
		char = string.sub(text, index_k, index_k)
		if char == "\r" then char = "\n" end
		result = result .. char
	end
	return result
end

function printTerminalHex(text, color, index_stamp)
	if color == nil then
		color = green
	end
	for index_l = 1, string.len(text) do
		char_num = string.byte(text, index_l)
		char_hex = formatNumbertoHex(char_num)
		terminal:print(terminalX * 8, terminalY * 8, char_hex, color)
		if index_stamp ~= nil then
			printTerminalIndex(index_stamp)
		end
		terminalX = terminalX + 2
		if terminalX >= 60 then
			terminalX = 0
			terminalY = terminalY + 3
		end
		terminalMaxY()
	end
end

function printTerminalIndex(index_num)
	index_hex = formatNumbertoHex(index_num)
	terminal:print((terminalX) * 8, (terminalY + 1) * 8, index_hex, green)
end

function formatNumbertoHex(number)
	result = ""
	if number <= 9 then
		result = string.format&#40;"0%d", number&#41;
	else
		result = string.format&#40;"%2X", number&#41;
	end
	return result
end

function printTerminalAlpha&#40;text, color&#41;
	if color == nil then
		color = green
	end
	for index_m = 1, string.len&#40;text&#41; do
		char = string.sub&#40;text, index_m, index_m&#41;
		if char == "\n" then
			terminalY = terminalY + 1
			terminalX = 0
		else
			terminal&#58;print&#40;terminalX * 8, terminalY * 8, char, green&#41;
			terminalX = terminalX + 1
			if terminalX >= 60 then
				terminalX = 0
				terminalY = terminalY + 3
			end
		end
		terminalMaxY&#40;&#41;
	end
end

-- begin main program loop
printTerminal&#40;"serial init... ", green&#41;
System.sioInit&#40;4800&#41;
System.sleep&#40;30&#41;

sio_buffin = System.sioRead&#40;&#41;
if sio_buffin ~= "" then
	sio_remote = 2
end

while time < 6000 do
	if sio_buffin == "" then
		sio_buffin = System.sioRead&#40;&#41;
	end

	if sio_remote <= 1 then
		if sio_remote == 0 then
			printTerminal&#40;"remote missing... ", green&#41;
			sio_remote = 1
		end
		if sio_buffin ~= "" then
			if string.byte&#40;sio_buffin, 1&#41; == 0x00 then
				sio_buffin = string.sub&#40;sio_buffin, 2, -1&#41;
			end
			sio_remote = 2
		end
	end

	if sio_remote == 2 then
		printTerminal&#40;"remote present...\n", green&#41;
		printTerminal&#40;"starting echo... ", green&#41;
		sio_remote = 3
	end

	if sio_buffin ~= "" then
		sio_timep = sio_time
		sio_time = time
		for index_n = 1, string.len&#40;sio_buffin&#41; do
			sio_bytein = string.byte&#40;sio_buffin, index_n&#41;
			-- check for frame start
			if sio_bytein == 0xF0 then
				-- remove extra frame start
				if sio_countF0 >= 5 or sio_countF0 == -1 then
					sio_byteout = 0xF8
					sio_index = 1
					sio_countF0 = -1
				end
				if sio_countF0 ~= -1 then
					sio_countF0 = sio_countF0 + 1
				end
			end
			-- check for frame okay to send
			if sio_bytein == 0xF8 then
				sio_cts = 1
				sio_txmsgs = sio_txmsgs + 1
			end
			-- check if remote was removed
			if sio_bytein == 0x00 then
				if &#40;sio_time - sio_timep&#41; > 60 then
					sio_reset = 1
				end
			end
			-- check command and set frame acknowledge
			if sio_index == 3 and sio_bytein ~= 0xFE then
				if &#40;sio_bytein & 0x01&#41; == 0 then
					sio_phase = 0xFA
				else
					sio_phase = 0xFB
				end
			end
			-- check for frame end
			if sio_bytein == 0xFE then
				sio_byteout = sio_phase
				sio_index = 0
				sio_msgs = sio_rxmsgs + 1
			else
				sio_index = sio_index + 1
			end
		end

		printTerminalHex&#40;sio_buffin, nil, nil&#41;
		sio_buffin = ""
	end

	if sio_byteout ~= nil then
		System.sioWrite&#40;string.char&#40;sio_byteout&#41;&#41;
		printTerminalHex&#40;string.char&#40;sio_byteout&#41;, blue, nil&#41;
		sio_byteout = nil
	end

	if sio_rxmsgs >= 2 and sio_remote == 3 then
		if sio_rts == 0 then
			printTerminal&#40;"remote init... ", green&#41;
			System.sioWrite&#40;string.char&#40;0xF0&#41;&#41;
			printTerminalHex&#40;string.char&#40;0xF0&#41;, blue, nil&#41;
			sio_rts = 1
		end
	end

	if sio_cts == 1 then
		if sio_txmsgs == 1 then
			sio_buffout = string.char&#40;0xFD, 0x03, 0x01, 0x02, 0xFE&#41;
		elseif sio_txmsgs == 2 then
			sio_buffout = string.char&#40;0xFD, 0x02, 0x00, 0x02, 0xFE&#41;
		end
		sio_cts = 0
	end

	if sio_buffout ~= "" then
		System.sioWrite&#40;sio_buffout&#41;
		printTerminalHex&#40;sio_buffout, blue, nil&#41;
		sio_buffout = ""
	end

	if sio_reset == 1 then
		terminal&#58;fillRect&#40;0, 0, 480, 16&#41; 
		terminalHeadX = 0
		terminalHeadY = 0
		UpdateScreen&#40;&#41;
		sio_reset = 0
		sio_remote = 0
	end

	ping = ping + 1
	if ping == 60 then
		ping = 0
		printTerminalAlpha&#40;" &#58;", nil&#41;
	end

	keypad = Controls.read&#40;&#41;
	if keypad&#58;start&#40;&#41; then
		break
	elseif keypad&#58;select&#40;&#41; then
		while Controls.read&#40;&#41;&#58;select&#40;&#41; == false do
		end
	end

	UpdateScreen&#40;&#41;
	time = time + 1
end
Post Reply