M:Robe 500 Fix a bug in the UART receive buffer - remote does not appear to stop working anymore, add support for interupt driven transmit, add very rough remote LCD support.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@20706 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Karl Kurbjun 2009-04-14 05:17:03 +00:00
parent 140c7e6f66
commit 5b6af5e560
4 changed files with 211 additions and 168 deletions

View file

@ -186,27 +186,26 @@ int button_read_device(int *data)
} }
retval=uart1_gets_queue(r_buffer, 5); retval=uart1_gets_queue(r_buffer, 5);
do
for(calbuf=0;calbuf<4;calbuf++)
{ {
for(calbuf=0;calbuf<4;calbuf++) if((r_buffer[calbuf]&0xF0)==0xF0 && (r_buffer[calbuf+1]&0xF0)!=0xF0)
{ break;
if((r_buffer[calbuf]&0xF0)==0xF0 && (r_buffer[calbuf+1]&0xF0)!=0xF0) }
break; calbuf++;
} if(calbuf==5)
calbuf++; calbuf=0;
if(calbuf==5) if(retval>=0)
calbuf=0; {
if(retval>=0) uart1_clear_queue();
{ r_button |= r_buffer[calbuf];
r_button |= r_buffer[calbuf]; oldbutton=r_button;
oldbutton=r_button; }
} else
else {
{ r_button=oldbutton;
r_button=oldbutton; }
}
} while((retval=uart1_gets_queue(r_buffer, 5))>=5);
return r_button; return r_button;
} }
@ -226,6 +225,5 @@ void GIO14(void)
read_battery_inputs(); read_battery_inputs();
break; break;
} }
//touch_available = true;
IO_INTC_IRQ2 = (1<<3); /* IRQ_GIO14 == 35 */ IO_INTC_IRQ2 = (1<<3); /* IRQ_GIO14 == 35 */
} }

View file

@ -33,17 +33,22 @@ static enum remote_control_states
REMOTE_CONTROL_NOP, REMOTE_CONTROL_NOP,
REMOTE_CONTROL_POWER, REMOTE_CONTROL_POWER,
REMOTE_CONTROL_MASK, REMOTE_CONTROL_MASK,
REMOTE_CONTROL_DRAW1, REMOTE_CONTROL_DRAW,
REMOTE_CONTROL_DRAW_PAUSE1,
REMOTE_CONTROL_DRAW2,
REMOTE_CONTROL_DRAW_PAUSE2,
REMOTE_CONTROL_SLEEP REMOTE_CONTROL_SLEEP
} remote_state_control = REMOTE_CONTROL_NOP; } remote_state_control = REMOTE_CONTROL_NOP, remote_state_control_next;
static enum remote_draw_states
{
DRAW_TOP,
DRAW_BOTTOM,
DRAW_PAUSE,
} remote_state_draw = DRAW_TOP, remote_state_draw_next;
bool remote_initialized=true; bool remote_initialized=true;
unsigned char remote_contrast=DEFAULT_REMOTE_CONTRAST_SETTING; unsigned char remote_contrast=DEFAULT_REMOTE_CONTRAST_SETTING;
unsigned char remote_power=0x00; unsigned char remote_power=0x00;
unsigned char remote_mask=0x00;
/*** hardware configuration ***/ /*** hardware configuration ***/
@ -54,7 +59,7 @@ int lcd_remote_default_contrast(void)
void lcd_remote_sleep(void) void lcd_remote_sleep(void)
{ {
remote_state_control=REMOTE_CONTROL_SLEEP; remote_state_control_next=REMOTE_CONTROL_SLEEP;
} }
void lcd_remote_powersave(bool on) void lcd_remote_powersave(bool on)
@ -62,19 +67,19 @@ void lcd_remote_powersave(bool on)
if(on) if(on)
{ {
remote_power|=0xC0; remote_power|=0xC0;
remote_state_control=REMOTE_CONTROL_POWER; remote_state_control_next=REMOTE_CONTROL_POWER;
} }
else else
{ {
remote_power&=~(0xC0); remote_power&=~(0xC0);
remote_state_control=REMOTE_CONTROL_POWER; remote_state_control_next=REMOTE_CONTROL_POWER;
} }
} }
void lcd_remote_set_contrast(int val) void lcd_remote_set_contrast(int val)
{ {
remote_contrast=(char)val; remote_contrast=(char)val;
remote_state_control=REMOTE_CONTROL_POWER; remote_state_control_next=REMOTE_CONTROL_POWER;
} }
void lcd_remote_set_invert_display(bool yesno) void lcd_remote_set_invert_display(bool yesno)
@ -82,12 +87,6 @@ void lcd_remote_set_invert_display(bool yesno)
(void)yesno; (void)yesno;
} }
/* turn the display upside down (call lcd_remote_update() afterwards) */
void lcd_remote_set_flip(bool yesno)
{
(void)yesno;
}
bool remote_detect(void) bool remote_detect(void)
{ {
return true; return true;
@ -96,32 +95,41 @@ bool remote_detect(void)
void lcd_remote_on(void) void lcd_remote_on(void)
{ {
remote_power|=0x80; remote_power|=0x80;
remote_state_control=REMOTE_CONTROL_POWER; remote_state_control_next=REMOTE_CONTROL_POWER;
} }
void lcd_remote_off(void) void lcd_remote_off(void)
{ {
remote_power&=~(0x80); remote_power&=~(0x80);
remote_state_control=REMOTE_CONTROL_POWER; remote_state_control_next=REMOTE_CONTROL_POWER;
} }
unsigned char lcd_remote_test[16]= /* This is the maximum transfer size to the remote (op 0x51= 7 bytes setup+79
{0x80,0xFF,0x80,0x00,0xFF,0x89,0x89,0x00,0xC1,0x89,0x8F,0x80,0xFF,0x80,0,0}; * bytes screen data+xor+sum
*/
unsigned char remote_payload[88];
unsigned char remote_payload_size;
bool remote_repeat_draw=false;
unsigned char remote_draw_x, remote_draw_y,
remote_draw_width, remote_draw_height;
/* Monitor remote hotswap */ /* Monitor remote hotswap */
static void remote_tick(void) static void remote_tick(void)
{ {
unsigned char i; unsigned char i;
unsigned char remote_payload[10], remote_payload_size; static unsigned char pause_length=0;
unsigned char remote_check_xor, remote_check_sum;
if(remote_state_control!=REMOTE_CONTROL_DRAW)
remote_state_control=remote_state_control_next;
switch (remote_state_control) switch (remote_state_control)
{ {
case REMOTE_CONTROL_IDLE: case REMOTE_CONTROL_IDLE:
remote_payload_size=0; remote_payload_size=0;
remote_state_control=REMOTE_CONTROL_IDLE; remote_state_control=REMOTE_CONTROL_IDLE;
break; break;
case REMOTE_CONTROL_NOP: case REMOTE_CONTROL_NOP:
remote_payload[0]=0x11; remote_payload[0]=0x11;
remote_payload[1]=0x30; remote_payload[1]=0x30;
@ -129,6 +137,7 @@ static void remote_tick(void)
remote_payload_size=2; remote_payload_size=2;
remote_state_control=REMOTE_CONTROL_NOP; remote_state_control=REMOTE_CONTROL_NOP;
break; break;
case REMOTE_CONTROL_POWER: case REMOTE_CONTROL_POWER:
remote_payload[0]=0x31; remote_payload[0]=0x31;
remote_payload[1]=remote_power; remote_payload[1]=remote_power;
@ -137,51 +146,65 @@ static void remote_tick(void)
remote_payload_size=3; remote_payload_size=3;
remote_state_control=REMOTE_CONTROL_NOP; remote_state_control=REMOTE_CONTROL_NOP;
break; break;
case REMOTE_CONTROL_MASK: case REMOTE_CONTROL_MASK:
remote_payload[0]=0x41; remote_payload[0]=0x41;
remote_payload[1]=0x94; remote_payload[1]=remote_mask;
remote_payload_size=2; remote_payload_size=2;
remote_state_control=REMOTE_CONTROL_NOP; remote_state_control=REMOTE_CONTROL_NOP;
break; break;
case REMOTE_CONTROL_DRAW1:
case REMOTE_CONTROL_DRAW:
remote_payload[0]=0x51; remote_payload[0]=0x51;
remote_payload[1]=0x80; remote_payload[1]=0x80;
remote_payload[2]=14; remote_payload[2]=remote_draw_width;
remote_payload[3]=0; remote_payload[3]=remote_draw_x;
remote_payload[4]=0;
remote_payload[5]=14;
remote_payload[6]=8;
remote_payload_size=7; remote_payload[5]=remote_draw_x+remote_draw_width;
remote_state_control=REMOTE_CONTROL_DRAW_PAUSE1; remote_payload_size=7+remote_payload[2];
break;
case REMOTE_CONTROL_DRAW_PAUSE1:
remote_payload[0]=0x11;
remote_payload[1]=0x30;
remote_payload_size=2; switch (remote_state_draw)
remote_state_control=REMOTE_CONTROL_DRAW2; {
case DRAW_TOP:
remote_payload[4]=0;
remote_payload[6]=8;
pause_length=6;
remote_state_draw_next=DRAW_BOTTOM;
remote_state_draw=DRAW_PAUSE;
break;
case DRAW_BOTTOM:
remote_payload[4]=8;
remote_payload[6]=16;
pause_length=6;
remote_state_draw_next=DRAW_TOP;
remote_state_draw=DRAW_PAUSE;
break;
case DRAW_PAUSE:
remote_payload_size=0;
if(--pause_length==0)
{
if(remote_state_draw_next==DRAW_TOP)
remote_state_control=REMOTE_CONTROL_NOP;
remote_state_draw=remote_state_draw_next;
}
else
remote_state_draw=DRAW_PAUSE;
break;
default:
remote_payload_size=0;
break;
}
break; break;
case REMOTE_CONTROL_DRAW2:
remote_payload[0]=0x51;
remote_payload[1]=0x80;
remote_payload[2]=14;
remote_payload[3]=0;
remote_payload[4]=8;
remote_payload[5]=14;
remote_payload[6]=16;
remote_payload_size=7;
remote_state_control=REMOTE_CONTROL_DRAW_PAUSE2;
break;
case REMOTE_CONTROL_DRAW_PAUSE2:
remote_payload[0]=0x11;
remote_payload[1]=0x30;
remote_payload_size=2;
remote_state_control=REMOTE_CONTROL_NOP;
break;
case REMOTE_CONTROL_SLEEP: case REMOTE_CONTROL_SLEEP:
remote_payload[0]=0x71; remote_payload[0]=0x71;
remote_payload[1]=0x30; remote_payload[1]=0x30;
@ -189,6 +212,7 @@ static void remote_tick(void)
remote_payload_size=2; remote_payload_size=2;
remote_state_control=REMOTE_CONTROL_IDLE; remote_state_control=REMOTE_CONTROL_IDLE;
break; break;
default: default:
remote_payload_size=0; remote_payload_size=0;
break; break;
@ -199,46 +223,25 @@ static void remote_tick(void)
return; return;
} }
remote_check_xor=remote_payload[0];
remote_check_sum=remote_payload[0];
for(i=1; i<remote_payload_size; i++)
{
remote_check_xor^=remote_payload[i];
remote_check_sum+=remote_payload[i];
}
if(remote_payload[0]==0x51) if(remote_payload[0]==0x51)
{ {
unsigned char offset; for(i=7; i<remote_payload_size; i++)
unsigned char x;
if(remote_payload[4]==8)
{ {
offset=79; remote_payload[i]=
lcd_remote_framebuffer[remote_payload[4]>>3][i+remote_draw_x-7];
} }
else
{
offset=0;
}
for (x = 0; x < 14; x++)
{
remote_check_xor^=lcd_remote_test[x];
remote_check_sum+=lcd_remote_test[x];
}
uart1_puts(remote_payload, remote_payload_size);
lcd_remote_test[14]=remote_check_xor;
lcd_remote_test[15]=remote_check_sum;
uart1_puts(lcd_remote_test, 16);
} }
else
/* Calculate the xor and sum to place in the payload */
remote_payload[remote_payload_size]=remote_payload[0];
remote_payload[remote_payload_size+1]=remote_payload[0];
for(i=1; i<remote_payload_size; i++)
{ {
remote_payload[remote_payload_size]=remote_check_xor; remote_payload[remote_payload_size]^=remote_payload[i];
remote_payload[remote_payload_size+1]=remote_check_sum; remote_payload[remote_payload_size+1]+=remote_payload[i];
uart1_puts(remote_payload, remote_payload_size+2);
} }
uart1_puts(remote_payload, remote_payload_size+2);
} }
void lcd_remote_init_device(void) void lcd_remote_init_device(void)
@ -247,6 +250,8 @@ void lcd_remote_init_device(void)
if (remote_detect()) if (remote_detect())
lcd_remote_on(); lcd_remote_on();
lcd_remote_update();
/* put the remote control in the tick task */ /* put the remote control in the tick task */
tick_add_task(remote_tick); tick_add_task(remote_tick);
} }
@ -255,33 +260,28 @@ void lcd_remote_init_device(void)
This must be called after all other LCD functions that change the display. */ This must be called after all other LCD functions that change the display. */
void lcd_remote_update(void) void lcd_remote_update(void)
{ {
if(remote_state_control!=REMOTE_CONTROL_DRAW1 lcd_remote_update_rect(0, 0, LCD_REMOTE_WIDTH, LCD_REMOTE_HEIGHT);
&& remote_state_control!=REMOTE_CONTROL_DRAW_PAUSE1
&& remote_state_control!=REMOTE_CONTROL_DRAW2
&& remote_state_control!=REMOTE_CONTROL_DRAW_PAUSE2)
{
remote_state_control=REMOTE_CONTROL_DRAW1;
}
} }
/* Update a fraction of the display. */ /* Update a fraction of the display. */
void lcd_remote_update_rect(int x, int y, int width, int height) void lcd_remote_update_rect(int x, int y, int width, int height)
{ {
(void)x; remote_draw_x=x;
(void)y; remote_draw_y=y;
(void)width; remote_draw_width=width;
(void)height; remote_draw_height=height;
lcd_remote_update();
remote_state_control=REMOTE_CONTROL_DRAW;
} }
void _remote_backlight_on(void) void _remote_backlight_on(void)
{ {
remote_power|=0x40; remote_power|=0x40;
remote_state_control=REMOTE_CONTROL_POWER; remote_state_control_next=REMOTE_CONTROL_POWER;
} }
void _remote_backlight_off(void) void _remote_backlight_off(void)
{ {
remote_power&=~(0x40); remote_power&=~(0x40);
remote_state_control=REMOTE_CONTROL_POWER; remote_state_control_next=REMOTE_CONTROL_POWER;
} }

View file

@ -27,37 +27,48 @@
#define MAX_UART_BUFFER 31 #define MAX_UART_BUFFER 31
#define SEND_RING_SIZE 256 #define SEND_RING_SIZE 256
#define RECIEVE_RING_SIZE 20 #define RECEIVE_RING_SIZE 20
char char
// uart1_send_buffer_ring[SEND_RING_SIZE], uart1_send_buffer_ring[SEND_RING_SIZE],
uart1_recieve_buffer_ring[RECIEVE_RING_SIZE]; uart1_receive_buffer_ring[RECEIVE_RING_SIZE];
//static unsigned int uart1_send_count, uart1_send_read, uart1_send_write; static volatile int uart1_send_count, uart1_send_read, uart1_send_write;
static unsigned int uart1_recieve_count, uart1_recieve_read, uart1_recieve_write; static volatile int uart1_receive_count, uart1_receive_read, uart1_receive_write;
void uart_init(void) void uart_init(void)
{ {
// 8-N-1 // 8-N-1
IO_UART1_MSR = 0x8000; IO_UART1_MSR = 0xC400;
IO_UART1_BRSR = 0x0057; IO_UART1_BRSR = 0x0057;
IO_UART1_RFCR = 0x8010; /* Trigger later */ IO_UART1_RFCR = 0x8020; /* Trigger later */
IO_UART1_TFCR = 0x0000; /* Trigger level */
/* gio 27 is input, uart1 rx /* gio 27 is input, uart1 rx
gio 28 is output, uart1 tx */ gio 28 is output, uart1 tx */
IO_GIO_DIR1 |= (1<<11); /* gio 27 */ IO_GIO_DIR1 |= (1<<11); /* gio 27 */
IO_GIO_DIR1 &= ~(1<<12); /* gio 28 */ IO_GIO_DIR1 &= ~(1<<12); /* gio 28 */
/* init the recieve buffer */ /* init the receive buffer */
uart1_recieve_count=0; uart1_receive_count=0;
uart1_recieve_read=0; uart1_receive_read=0;
uart1_recieve_write=0; uart1_receive_write=0;
/* init the send buffer */
uart1_send_count=0;
uart1_send_read=0;
uart1_send_write=0;
/* Enable the interrupt */ /* Enable the interrupt */
IO_INTC_EINT0 |= INTR_EINT0_UART1; IO_INTC_EINT0 |= INTR_EINT0_UART1;
} }
/* This function is not interrupt driven */
void uart1_putc(char ch) void uart1_putc(char ch)
{ {
/* Wait for the interupt driven puts to finish */
while(uart1_send_count>0);
/* Wait for room in FIFO */ /* Wait for room in FIFO */
while ((IO_UART1_TFCR & 0x3f) >= 0x20); while ((IO_UART1_TFCR & 0x3f) >= 0x20);
@ -67,45 +78,73 @@ void uart1_putc(char ch)
void uart1_puts(const char *str, int size) void uart1_puts(const char *str, int size)
{ {
int count=0; if(size>SEND_RING_SIZE)
while (count<size) panicf("Too much data passed to uart1_puts");
/* Wait for the previous transfer to finish */
while(uart1_send_count>0);
memcpy(uart1_send_buffer_ring, str, size);
/* Disable interrupt while modifying the pointers */
IO_INTC_EINT0 &= ~INTR_EINT0_UART1;
uart1_send_count=size;
uart1_send_read=0;
/* prime the hardware buffer */
while(((IO_UART1_TFCR & 0x3f) < 0x20) && (uart1_send_count > 0))
{ {
uart1_putc(str[count]); IO_UART1_DTRR=uart1_send_buffer_ring[uart1_send_read++];
count++; uart1_send_count--;
} }
/* Enable interrupt */
IO_INTC_EINT0 |= INTR_EINT0_UART1;
}
void uart1_clear_queue(void)
{
/* Disable interrupt while modifying the pointers */
IO_INTC_EINT0 &= ~INTR_EINT0_UART1;
uart1_receive_write=0;
uart1_receive_count=0;
uart1_receive_read=0;
/* Enable interrupt */
IO_INTC_EINT0 |= INTR_EINT0_UART1;
} }
/* This function returns the number of bytes left in the queue after a read is done (negative if fail)*/ /* This function returns the number of bytes left in the queue after a read is done (negative if fail)*/
int uart1_gets_queue(char *str, unsigned int size) int uart1_gets_queue(char *str, int size)
{ {
/* Disable the interrupt while modifying the pointers */
IO_INTC_EINT0 &= ~INTR_EINT0_UART1; IO_INTC_EINT0 &= ~INTR_EINT0_UART1;
int retval; int retval;
if(uart1_recieve_count<size) if(uart1_receive_count<size)
{ {
retval= -1; retval= -1;
} }
else else
{ {
if(uart1_recieve_read+size<RECIEVE_RING_SIZE) if(uart1_receive_read+size<=RECEIVE_RING_SIZE)
{ {
memcpy(str,uart1_recieve_buffer_ring+uart1_recieve_read,size); memcpy(str,uart1_receive_buffer_ring+uart1_receive_read,size);
}
else
{
int tempcount=(RECIEVE_RING_SIZE-uart1_recieve_read);
memcpy(str,uart1_recieve_buffer_ring+uart1_recieve_read,tempcount);
memcpy(str+tempcount,uart1_recieve_buffer_ring,size-tempcount);
}
uart1_recieve_count-=size;
if(uart1_recieve_read+size<RECIEVE_RING_SIZE)
uart1_recieve_read+=size;
else
uart1_recieve_read=size-(RECIEVE_RING_SIZE-uart1_recieve_read);
retval=uart1_recieve_count; uart1_receive_read+=size;
}
else
{
int tempcount=(RECEIVE_RING_SIZE-uart1_receive_read);
memcpy(str,uart1_receive_buffer_ring+uart1_receive_read,tempcount);
memcpy(str+tempcount,uart1_receive_buffer_ring,size-tempcount);
uart1_receive_read=size-tempcount;
}
uart1_receive_count-=size;
retval=uart1_receive_count;
} }
/* Enable the interrupt */ /* Enable the interrupt */
@ -114,23 +153,29 @@ int uart1_gets_queue(char *str, unsigned int size)
return retval; return retval;
} }
/* UART1 receive interupt handler */ /* UART1 receive/transmit interupt handler */
void UART1(void) void UART1(void)
{ {
while (IO_UART1_RFCR & 0x3f) while (IO_UART1_RFCR & 0x3f)
{ {
if (uart1_recieve_count > RECIEVE_RING_SIZE) if (uart1_receive_count > RECEIVE_RING_SIZE)
panicf("UART1 buffer overflow"); panicf("UART1 receive buffer overflow");
else else
{ {
if(uart1_recieve_write>=RECIEVE_RING_SIZE) if(uart1_receive_write>=RECEIVE_RING_SIZE)
uart1_recieve_write=0; uart1_receive_write=0;
uart1_recieve_buffer_ring[uart1_recieve_write] = IO_UART1_DTRR & 0xff; uart1_receive_buffer_ring[uart1_receive_write]=IO_UART1_DTRR & 0xff;
uart1_recieve_write++; uart1_receive_write++;
uart1_recieve_count++; uart1_receive_count++;
} }
} }
while ( ((IO_UART1_TFCR & 0x3f) < 0x20) && (uart1_send_count > 0) )
{
IO_UART1_DTRR=uart1_send_buffer_ring[uart1_send_read++];
uart1_send_count--;
}
IO_INTC_IRQ0 = INTR_IRQ0_UART1; IO_INTC_IRQ0 = INTR_IRQ0_UART1;
} }

View file

@ -23,10 +23,10 @@
void uart_init(void); void uart_init(void);
bool uart1_available(void); bool uart1_available(void);
int uart1_gets_queue(char *, unsigned int); int uart1_gets_queue(char *, int);
void uart1_puts(const char *str, int size); void uart1_puts(const char *str, int size);
void uart1_gets(char *str, unsigned int size); void uart1_gets(char *str, int size);
void uart1_putc(char ch); void uart1_putc(char ch);
void uart1_clear_queue(void);
#endif #endif