/* $Id: ircontrol.c,v 1.4 2000/10/17 13:15:51 henriken Exp $
 *
 * Remote control IR code receiver
 *
 * Copyright (c) 1999 Bjorn Wesen
 *
 * This driver assumes that an IR receiver is connected to general port A
 * pin 7 (PA7) and that the signal is normally a 0 (going to 1 for the
 * startbit) because we use Port A's IRQ triggering facility which can only
 * trigger an IRQ when it is a 1.
 * 
 * What happens then, is that a 4 kHz timer is started, generating IRQ's 
 * to sample PA7 for 40 ms (generating 160 samples). The minimum pulse-width
 * entering is 0.5 ms, so this assures that we sample at least 2 times per
 * pulse. After the 40 ms, the timer and IRQ's are turned off and the data is
 * processed to see if a valid startbit and code was received, and processes
 * that are waiting for a code are awoken. After this we turn on the PA7 IRQ
 * again to wait for the next code.
 *
 */

/* 
 Some info from: 
  http://www.ee.washington.edu/eeca/text/ir_decode.txt
  http://www.armory.com/~spcecdt/remote/
  http://www.armory.com/~spcecdt/remote/RC5codes

There are at least two international standards which are used by remote 
controls to encode the commands, the RC5 and RECS 80 code. 
The RECS 80 code uses pulse length modulation. Each bit to be transmitted 
is encoded by a high level of the duration T followed by a low level of 
duration 2T representing a logical '0' or 3T representing a logical '1'. 


  T 2T T 3T  T 2T
  _    _     _ 
 | |  | |   | |
_| |__| |___| |__
  0    1     0

Notice that a '1' takes more time to be transmitted than a '0'. 

The RC 5 code instead has a uniform duration of all bits. A transition in 
the middle of the time interval assigned to each bit encodes the logical 
value. A '0' is encoded by a high to low transition and a '1' by a low to 
high transition. Therefore we need additional transitions at the beginning
of each bit to set the proper start level if a series of equal bits is sent.
We don't need this additional transition if the next bit has a different value.
This is also called a 'biphase' code. 

|1.Bit|2.Bit|3.Bit|4.Bit|             
 __    __       __    __
   |  |  |     |  |  |  
   |__|  |_____|  |__|  
   0     0     1     1

How are commands like volume control or channel selction encoded? In the case 
of the RC5 code there is an international standard. Every command is encoded 
by 14 bits. The first two bits S are startbits to allow the receiver to adjust
the automatic gain control and to synchronize. Next a bit T follows, that 
toggles with every new keystroke. Next is the address A of the device which 
shall respond to the command. At last the command itself follows. 


  | S | S | T | A4 | A3 | A2 | A1 | A0 | C5 | C4 | C3 | C2 | C1 | C0 |

  2 run-in bits to adjust the AGC level in the receiver IC  
  1 check bit
  5 system address bits  
  6 command bits.

These have been assigned as follows (RC5):
System address     Equipment  
  0                TV1
  1                TV2
  2                Teletext
  5                VCR1 - Video recorder  
  6                VCR2
  7                experimental
 16                preamplifier 
 17                receiver/tuner
 18                tape/cassette recorder 
 19                experimental
 20                CD player

Command code      Function 
 0-9               0-9 
 12                standby
 13                mute 
 14                presets 
 16                volume +
 17                volume -                 
 18                brightness +
 19                brightness - 
 20                colour saturation +
 21                colour saturation - 
 22                bass +
 23                bass - 
 24                treble + 
 25                treble -
 26                balance right 
 27                balance left
 48                pause 
 50                fast reverse
 52                fast forward 
 53                play 
 54                stop
 55                record 
 63                system select

The basic timing is derived from a 36KHZ oscillator.
The code is transmitted in biphase format. In this system, a logic 1 is 
transmitted as a half bit time without signal, followed by a half bit time
with signal. A logic 0 has exactly the opposite structure. Each half bit 
consists of 32 shorter pulses. Each transmitted bit has a length of 1.778 msec,
the shorter pulses have a pulse width of 6.9444 usec on time and 20.8332 usec
off time. A complete dataword has a length of 24.889 msec, and is always
transmitted completely. If the key is held pressed the code is repeated in
intervals of 64 bit times (ie 113.778 msec). 



--------------------
RCA
     +------------------+         +-+ +-+   +-+         +-+         +---
     |                  |         | | | |   | |         | |         |
 ----+                  +---------+ +-+ +---+ +- . . . -+ +---------+
     |------- t1 -------|--- t2 --|T|T|T|3T |             |--- t3 --|
                                  |'0'| '1' |   

t1 = 4.2ms
t2 = 3.8ms
t3 = 7.8ms
T  = 600us
Each packet is 24 bits in length, and does not appear to exhibit the
coding scheme where the second 12 bits are the logical complement of
the first twelve. Here is an example of what I decoded by hand:

*/

#include <linux/module.h>
#include <linux/sched.h>
#include <linux/malloc.h>
#include <linux/ioport.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/string.h>

#include <asm/svinto.h>
#include <asm/io.h>
#include <asm/system.h>

#define IRCONTROL_MAJOR 62  /* experimental MAJOR number */

#define PA_IRQ_NBR     11
#define TIMER1_IRQ_NBR 3

/*
 * we use a source of 230400 Hz and a divider of 57 => 4042 Hz
 * 230400 / 115 = 2003.47 Hz
 */
#define FREQ_BASE 230400
#define FREQ_DIVIDER 57
#define SAMLE_FREQ (FREQ_BASE / FREQ_DIVIDER)
#define SAMPLE_TIME_MS 40
#define NUM_SAMPLES_CALC (SAMPLE_FREQ * SAMPLE_TIME_MS / 1000 ) 
#define NUM_SAMPLE_BYTES (NUM_SAMPLES_CALC / 8)

#define IRBUFLEN 160   /* number of samples */

#define TYPE(dev)   (MINOR(dev) >> 4)  /* high nibble */
#define NUM(dev)    (MINOR(dev) & 0xf) /* low  nibble */

#define D(x)

static char ircontrol_name[] = "ircontrol";

static struct wait_queue *ir_wq;

static int ircontrol_read(struct inode *inode, struct file *filp, char *buf, int len);
static int ircontrol_open(struct inode *inode, struct file *filp);
static void ircontrol_release(struct inode *inode, struct file *filp);
static int ircontrol_select(struct inode *inode, struct file *filp, int mode, select_table *table);

struct file_operations ircontrol_fops = {
	NULL,             /* lseek()   */
	ircontrol_read,   /* read()    */
	NULL,             /* write()   */
	NULL,             /* readdir() */
	ircontrol_select, /* select()  */
	NULL,             /* ioctl()   */
	NULL,             /* mmap()    */
	ircontrol_open,   /* open()    */
	ircontrol_release,/* release() */
	NULL,             /* fsync()   */
	NULL,             /* fasync()  */
	NULL,             /* check_media_change() */
	NULL              /* revalidate() */
};

static void
start_pa7_irq()
{
	*R_IRQ_MASK1_SET = IO_STATE(R_IRQ_MASK1_SET, pa7, set);
}

static unsigned char irbuf[IRBUFLEN];
static unsigned char irbuf2[IRBUFLEN];
static int irbuf_ptr;
static int ir_available;


/* go through the sampled ircode in irbuf and see if its a valid code */

static void
process_ircode()
{



}


/* Port PA interrupt handler */

static void
pa_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
{
	/* this is a shared irq, so first check that its PA7 which is calling */
	
	if(!(*R_IRQ_MASK1_RD & IO_STATE(R_IRQ_MASK1_RD, pa7, active)))
		return;

	/* since we can't "ack" the IR bit, we simply turn off the PA7 irq */
	
	*R_IRQ_MASK1_CLR = IO_STATE(R_IRQ_MASK1_CLR, pa7, clr);

	/* now enable the timer1 so we can sample the IR code
	 * we use a source of 230400 Hz and a divider of 57 => 4042 Hz
	 * 230400 / 115 = 2003.47 Hz
	 */
	irbuf_ptr = 0;
	memset(irbuf, 0, IRBUFLEN * sizeof(*irbuf));

	*R_TIMER_CTRL = r_timer_ctrl_shadow = 
		(r_timer_ctrl_shadow &
		 ~IO_MASK(R_TIMER_CTRL, timerdiv1) &
		 ~IO_MASK(R_TIMER_CTRL, tm1) &
		 ~IO_MASK(R_TIMER_CTRL, clksel1)) | 
		IO_FIELD(R_TIMER_CTRL, timerdiv1, FREQ_DIVIDER) |
		IO_STATE(R_TIMER_CTRL, tm1, stop_ld) | 
		IO_FIELD(R_TIMER_CTRL, clksel1, 10);

	*R_TIMER_CTRL = r_timer_ctrl_shadow = 
		(r_timer_ctrl_shadow & ~IO_MASK(R_TIMER_CTRL, tm1)) |
		IO_STATE(R_TIMER_CTRL, tm1, run);

	/* enable timer1 irq */

	*R_IRQ_MASK0_SET = IO_STATE(R_IRQ_MASK0_SET, timer1, set);

	D(printk("pairq\n"));
}

/* Timer 1 interrupt handler */

static void
timer1_handler(int irq, void *dev_id, struct pt_regs *regs)
{
	unsigned char sample_dist;

	static unsigned char timer_scale[57] =
	{
		0,	1,	3,	5,	7,	8,	10,	12,
		14,	16,	17,	19,	21,	23,	25,	26,
		28,	30,	32,	33,	35,	37,	39,	41,
		42,	44,	46,	48,	50,	51,	53,	55,
		57,	58,	60,	62,	64,	66,	67,	69,
		71,	73,	75,	76,	78,	80,	82,	83,
		85,	87,	89,	91,	92,	94,	96,	98,
		100
	};
	
	
	/* acknowledge the timer1 irq */
	
	*R_TIMER_CTRL = r_timer_ctrl_shadow | 
		IO_STATE(R_TIMER_CTRL, i1, clr);

	/* sample the IR port */

        sample_dist = timer_scale[57 - *R_TIMER1_DATA]; /*  scale to percentage */
	irbuf[irbuf_ptr] = (*R_PORT_PA_READ & 0x80) | (sample_dist & 0x7f);
	
	irbuf_ptr++;

	/* bogey detection (abort if there is no start-bit) */

        if(irbuf_ptr <= 32 && ((irbuf[irbuf_ptr - 1] & 0x80) != 0x80)) {
		/* shut off the timer */
		
		*R_TIMER_CTRL = r_timer_ctrl_shadow = 
			(r_timer_ctrl_shadow & ~IO_MASK(R_TIMER_CTRL, tm1)) |
			IO_STATE(R_TIMER_CTRL, tm1, stop_ld);
		
		*R_IRQ_MASK0_CLR = IO_STATE(R_IRQ_MASK0_CLR, timer1, clr);
		
		/* restart pa7 irq to try to get a real code */
		
		start_pa7_irq();
		
	} else {

		if(irbuf_ptr >= IRBUFLEN) {
			
			/* tell our callers that there is new data */
			
			wake_up_interruptible(&ir_wq);
			
			/* done sampling, turn off timer1 */
			
			*R_TIMER_CTRL = r_timer_ctrl_shadow = 
				(r_timer_ctrl_shadow & ~IO_MASK(R_TIMER_CTRL, tm1)) |
				IO_STATE(R_TIMER_CTRL, tm1, stop_ld);
			
			*R_IRQ_MASK0_CLR = IO_STATE(R_IRQ_MASK0_CLR, timer1, clr);
			
			/* take a snapshot of the last data */
			memcpy(irbuf2, irbuf, IRBUFLEN * sizeof (*irbuf));
			
			ir_available = 1;
			
		}
	}
}

/* read waits for a code if there isn't one available already 
 * when read returns, it clears the ir_available flag. in other words, no two
 * reads will get the same data
 */

static int
ircontrol_read(struct inode *inode, struct file *filp, char *buf, int len)
{
	int rlen;

	D(printk("ircontrol_read\n"));

	if(!ir_available) {

		/* start the reception (if not already running) */
		
		start_pa7_irq();
		
		/* and wait until a code comes by */
		
		interruptible_sleep_on(&ir_wq);		
	}

	/* now we either got a signal, or there is actually a new code for us.
	 * in either case, we copy the last decoded code and return with it
	 */
	
	rlen = len < (IRBUFLEN * sizeof (*irbuf)) ? len : (IRBUFLEN * sizeof (*irbuf));
	
	memcpy(buf, irbuf2, rlen);

	ir_available = 0;
	return rlen;
}


static int 
ircontrol_select(struct inode *inode,
		 struct file *filp,
		 int mode,
		 select_table *table)
{
        if(!ir_available) {
		D(printk("ircontrol_select sleeping task\n"));
		start_pa7_irq();
		select_wait(&ir_wq, table);
		return 0;
	}
	D(printk("ircontrol_select ready\n"));
	return 1;
}


static int
ircontrol_open(struct inode *inode, struct file *filp)
{
	D(printk("ircontrol_open\n"));
	return 0;
}

static void
ircontrol_release(struct inode *inode, struct file *filp)
{
	D(printk("ircontrol_release\n"));
}

/* main driver initialization routine, called from mem.c */

int
ircontrol_init(void)
{
	int res;

	/* do the formalities */

	res = register_chrdev(IRCONTROL_MAJOR, ircontrol_name, &ircontrol_fops);
	if(res < 0) {
		printk(KERN_ERR "ircontrol: couldn't get a major number.\n");
		return res;
	}
	
	register_symtab(0);

	printk("IR-control driver v0.5, (c) 1999 Bjorn Wesen\n");

	/* all PA general pins that are not in use are inputs so we don't
	 * need to fiddle with R_PORT_PA_DIR
	 */

	/* grab the interrupts we need - the main vectors get enabled but
	 * the individual bits in the masks are not enabled yet 
	 */

	if(request_irq(PA_IRQ_NBR, pa_irq_handler, SA_SHIRQ,
		       ircontrol_name, NULL)) {
		printk("err: pa irq\n");
		return -1;
	}

	if(request_irq(TIMER1_IRQ_NBR, timer1_handler, 0,
		       ircontrol_name, NULL)) {
		printk("err: timer1 irq\n");
		return -1;
	}

	init_waitqueue(&ir_wq);

	return res;
}


