/* smc-ir.c - minimal IR receiver driver for XeLL
 *
 * Copyright (C) 2008 Georg Lukas <georg@boerde.de>
 *
 * This software is provided under the GNU GPL License v2.
 */
#include <cache.h>
#include <types.h>
#include <string.h>
#include <vsprintf.h>

volatile uint32_t *smc_base = (volatile uint32_t*)0x200ea001000LL;

static inline unsigned int swap32(unsigned int v)
{
	return ((v&0xFF) << 24) | ((v&0xFF00)<<8) | ((v&0xFF0000)>>8) | ((v&0xFF000000)>>24);
}


int smc_hasdata() {
	return (swap32(smc_base[0x94/4]) & 4);
}

int smc_get(uint32_t *msg) {
	int pos;
	if (swap32(smc_base[0x94/4]) & 4) {
		smc_base[0x94/4] = swap32(4);
		for (pos=0; pos < 4; pos++)
			msg[pos] = smc_base[0x90/4];
		smc_base[0x94/4] = 0;
		return 1;
	}
	return 0;
}

void smc_send(uint32_t *msg) {
	int pos;
	while (!(swap32(smc_base[0x84/4]) & 4));

	smc_base[0x84/4] = swap32(4);
	for (pos=0; pos < 4; pos++)
		smc_base[0x80/4] = msg[pos];
	smc_base[0x84/4] = 0;
}

int smc_ir_charcode(unsigned char* msg) {
	if (msg[0] == 0x83 && msg[1] == 0x23)
		return msg[3];

	return -1;
}

void smc_debug() {
	unsigned char msg[16];

	memset(msg, 0, 16);
	msg[0] = 0x16;
	smc_send(msg);

	while (1) {
	//	while (!smc_hasdata());

		memset(msg, 0, 16);

		if (smc_get(&msg)) {
			if (msg[0] == 0x83 && msg[1] == 0x11 && msg[2] == 0x01) {
				printf("NAKed Power!\n");
				memset(msg, 0, 16);
				msg[0] = 0x82;
				msg[1] = 0x04;
				msg[2] = 0x33;
				smc_send(msg);
				continue;
			}
			int i;
			printf("Received");
			for (i=0; i<16; i++)
				printf(" %02x", (uint32_t)msg[i]);
			printf("\n");
		}
	}
}
