📄 console.c
字号:
/* Console.c - Console peripheral with LCD and keyboard
* based on ODO WinCE reference platform.
*
* Copyright (C) ARM Limited. All rights reserved.
*
*
*/
#include "minperip.h"
#include "armul_mem.h"
#include "xlcd.h"
#include "console.h"
#define HOURGLASS_COUNT 20000 /* ARMulator cycles between display updates */
#define MAX_KBD_EVENTS 128 /* Maximum number of keyboard events queued */
#define TIMER_COUNT 1 /* ARMulator cycles between timer counts */
// Declare global variables to hold the display dimensions read in from peripherals.ami
unsigned lcd_width, lcd_height;
BEGIN_STATE_DECL(Console)
void *hourglass;
int XCounter;
LcdModel *TheLCD;
LcdEvent *TheEvent;
int TimeCounter;
int bigendSig;
int ntrans;
ARMword CpuIR;
ARMword CpuMR;
ARMword CpuISR;
ARMword CpuTIR;
ARMword CpuTVR;
ARMword DispCSR;
ARMword DispISR;
ARMword KbdCSR;
ARMword KbdISR;
ARMword KbdStack[MAX_KBD_EVENTS];
int KbdEventsIn, KbdEventsOut;
/* store details of peripheral registration */
ARMul_BusPeripAccessRegistration my_bpar;
END_STATE_DECL(Console)
/* Function prototypes */
static int MemAccess_Console(void *handle, struct ARMul_AccessRequest *req);
static void MemHourglass(void *handle, ARMword pc, ARMword instr);
static unsigned ConfigChange(void *handle, void *data );
static void IrqUpdate(ConsoleState *os, char *reason);
static void keyboard_queue_in(ConsoleState *os, int keycode);
static void keyboard_queue_out(ConsoleState *os);
BEGIN_INIT(Console)
{
unsigned err;
Hostif_PrettyPrint(state->hostif, config, ", LCD Console");
/* initialise Console peripheral. */
// read dimensions from the peripherals.ami file - on failure, set defaults
lcd_width = ToolConf_DLookupUInt(config, "LCD_WIDTH", LCD_WIDTH);
// tweak the width to make it DWORD aligned
//alignment_tweak = 4 - lcd_width % 4;
//if( alignment_tweak == 4 ) alignment_tweak = 0;
lcd_height = ToolConf_DLookupUInt(config, "LCD_HEIGHT", LCD_HEIGHT);
/* display_top = DISPLAY_PTR + (lcd_width+alignment_tweak)
* lcd_height / ( 8 / BITS_PER_PIXEL );
*/
LcdModelInit();
state->TheLCD = LcdModelCreate(20, 20, lcd_width, lcd_height);
if( !state->TheLCD ) return RDIError_Error;
state->TheEvent = (LcdEvent *)malloc(sizeof(LcdEvent));
LcdModelCheckEvents(state->TheLCD, state->TheEvent);
/* Install an hourglass callback to handle queued keyboard events */
state->hourglass = ARMulif_InstallHourglass(&state->coredesc, MemHourglass, state);
state->XCounter = HOURGLASS_COUNT;
/* Install handlers to cope with changes to the BigEnd signal */
ARMulif_InstallEventHandler( &state->coredesc, ConfigEventSel, ConfigChange, state );
//ARMul_InstallConfigChangeHandler(state,ConfigChange,os);
state->TimeCounter = TIMER_COUNT;
/* Initialize the keyboard state */
state->KbdEventsIn = 0;
state->KbdEventsOut = 0;
state->KbdISR = 0;
state->CpuIR = 0;
/* Register the peripheral in the memory map, cover LCD, Control reg. and Keyboard */
err = RDIError_NoError;
state->my_bpar.access_func = MemAccess_Console;
state->my_bpar.access_handle = state;
state->my_bpar.capabilities = PeripAccessCapability_Minimum;
err = ARMulif_ReadBusRange(&state->coredesc, state->hostif,
//ToolConf_FlatChild(config, (tag_t)"RANGE"),
0,
&state->my_bpar,
DISP_BASE,(KB_ISR+1)-DISP_BASE,"");
err = state->my_bpar.bus->bus_registerPeripFunc(BusRegAct_Insert,
&state->my_bpar);
if (err)
return err;
}
END_INIT(Console)
BEGIN_EXIT(Console)
/* Closedown the LCD panel */
LcdModelDestroy(state->TheLCD);
/* Close the LCD Model */
LcdModelClose();
END_EXIT(Console)
/* Peripheral memory access function *****************/
static int MemAccess_Console(void *handle, struct ARMul_AccessRequest *req)
{
ARMWord addr = req->req_address[0];
ARMWord *data = req->req_data;
unsigned type = req->req_access_type;
ConsoleState *os=(ConsoleState *)handle;
/* ODO model hardware registers */
if (acc_WRITE(type)) {
/* Write registers */
/* Deal with writes to the LCD display frame */
if (addr >= DISPLAY_PTR && addr < REG_BASE ) {
/* Deal with writes to the LCD display frame */
unsigned char *byte = (unsigned char *)data;
/* DEBUG - may not be initialised - determine endianness! */
if (os->bigendSig) {
switch (acc_WIDTH(type)) {
case BITS_8:
LcdModelWrite(os->TheLCD, addr-DISPLAY_PTR, byte[3]);
break;
case BITS_16:
LcdModelWrite(os->TheLCD, addr-DISPLAY_PTR, byte[3]);
LcdModelWrite(os->TheLCD, 1+addr-DISPLAY_PTR,byte[2]);
break;
case BITS_32:
LcdModelWrite(os->TheLCD, addr-DISPLAY_PTR, byte[3]);
LcdModelWrite(os->TheLCD, 1+addr-DISPLAY_PTR, byte[2]);
LcdModelWrite(os->TheLCD, 2+addr-DISPLAY_PTR, byte[1]);
LcdModelWrite(os->TheLCD, 3+addr-DISPLAY_PTR, byte[0]);
break;
}
}
else {
switch (acc_WIDTH(type)) {
case BITS_8:
LcdModelWrite(os->TheLCD, addr-DISPLAY_PTR, byte[0]);
break;
case BITS_16:
LcdModelWrite(os->TheLCD, addr-DISPLAY_PTR, byte[0]);
LcdModelWrite(os->TheLCD, 1+addr-DISPLAY_PTR,byte[1]);
break;
case BITS_32:
LcdModelWrite(os->TheLCD, addr-DISPLAY_PTR, byte[0]);
LcdModelWrite(os->TheLCD, 1+addr-DISPLAY_PTR, byte[1]);
LcdModelWrite(os->TheLCD, 2+addr-DISPLAY_PTR, byte[2]);
LcdModelWrite(os->TheLCD, 3+addr-DISPLAY_PTR, byte[3]);
break;
}
}
}
/* Write access to ODO control registers in */
/* the System ASIC and Housekeeping FPGA. */
switch (addr) {
/*
case DEBUG_WRITE_CH_ADDRESS:
fprintf(os->confd,"%c",*word);
break;
*/
case CPU_ISR:
os->CpuIR = *data;
return PERIP_OK;
case CPU_MR:
os->CpuMR = *data;
IrqUpdate(os, "write to CpuMR");
return PERIP_OK;
case DISP_CSR:
os->DispCSR |= *data & 0x3ffffff;
return PERIP_OK;
case KB_CSR:
os->KbdCSR = (os->KbdCSR & 0xff) | (*data & ~0xff);
return PERIP_OK;
case KB_ISR:
os->KbdISR = *data;
if (*data & KB_RDRF) {
/* Attempt to clear down outstanding keyboard irq */
keyboard_queue_out(os);
}
return PERIP_OK;
}
}
else {
/* Read Registers */
/* Read access to ODO control registers in */
/* the System ASIC and Housekeeping FPGA. */
switch (addr) {
case CPU_ISR:
*data = os->CpuIR;
return PERIP_OK;
case CPU_MR:
*data = os->CpuMR;
return PERIP_OK;
case DISP_CSR:
*data = os->DispCSR;
return PERIP_OK;
case DISP_ISR:
*data = os->DispISR;
return PERIP_OK;
case DISP_XSIZE:
*data = lcd_width;
return PERIP_OK;
case DISP_YSIZE:
*data = lcd_height;
return PERIP_OK;
case KB_CSR:
*data = os->KbdCSR;
return PERIP_OK;
case KB_ISR:
*data = os->KbdISR;
return PERIP_OK;
}
}
return PERIP_NODECODE;
}
/* Model event handlers ******************************/
static void MemHourglass(void *handle, ARMword pc, ARMword instr)
{
/* Event Handling - called at regular intervals by the ARMulator */
ConsoleState *os=(ConsoleState *)handle;
if (!os->XCounter--) {
os->XCounter=HOURGLASS_COUNT;
LcdModelCheckEvents(os->TheLCD, os->TheEvent);
/* Deal with Display / Keyboard events if required */
switch (os->TheEvent->Type) {
case LCDNone:
break;
case LCDKeyPress:
case LCDKeyRelease:
if (os->KbdCSR & KB_CLK_EN) {
/* Queue keyboard events (pulled off in same order) */
if (os->TheEvent->Type == LCDKeyRelease)
keyboard_queue_in(os, KEY_UP);
/* Check for extended keycode */
if ((os->TheEvent->KeyScanCode & 0xff00)>>8 != 0)
keyboard_queue_in(os, (os->TheEvent->KeyScanCode & 0xff00)>>8);
keyboard_queue_in(os, os->TheEvent->KeyScanCode & 0xff);
}
break;
}
}
}
static unsigned ConfigChange(void *handle, void *data )
{
((ConsoleState *)handle)->bigendSig = (((ARMul_Event*)data)->data1 == 1);
return RDIError_NoError;
}
/* IRQ generation ************************************/
/* MUST be called whenever the state of any relevant register changes */
static void IrqUpdate(ConsoleState *os, char *reason)
{
int irq = (os->CpuMR & os->CpuIR & KEYB_INTR); /* keyboard status/mask */
ARMulif_SetSignal( &(os->coredesc), RDIPropID_ARMSignal_IRQ, irq );
}
static void keyboard_irq(ConsoleState *os)
{
/* Trigger a Keyboard interrupt */
os->CpuIR |= KEYB_INTR;
os->KbdISR |= KB_RDRF;
IrqUpdate(os, "keyboard irq set");
}
static void keyboard_noirq(ConsoleState *os)
{
/* Clear down keyboard interrupt */
os->KbdISR &= ~KB_RDRF;
os->CpuIR &= ~KEYB_INTR;
IrqUpdate(os, "keyboard irq clear");
}
/* LCD/Keyboard helper functions *********************/
static void keyboard_queue_in(ConsoleState *os, int keycode)
{
/* Only generate irq if no other outstanding keys */
if (os->KbdEventsIn == os->KbdEventsOut) {
keyboard_irq(os);
os->KbdCSR = (os->KbdCSR & ~0xff) | keycode;
}
/* Always queue */
os->KbdStack[os->KbdEventsIn] = keycode;
if (++os->KbdEventsIn == MAX_KBD_EVENTS)
os->KbdEventsIn = 0;
}
static void keyboard_queue_out(ConsoleState *os)
{
if (os->KbdEventsIn != os->KbdEventsOut) {
/* key at KbdEventsOut is already in KbdCSR */
if (++os->KbdEventsOut == MAX_KBD_EVENTS)
os->KbdEventsOut = 0;
if (os->KbdEventsIn == os->KbdEventsOut) {
keyboard_noirq(os);
} else {
os->KbdCSR = (os->KbdCSR & ~0xff) | os->KbdStack[os->KbdEventsOut] & 0xff;
}
}
}
unsigned int getPixelsX( void ) {
return lcd_width;
}
unsigned int getPixelsY( void ) {
return lcd_height;
}
/*--- <SORDI STUFF> ---*/
#define SORDI_DLL_NAME_STRING "Console"
#define SORDI_DLL_DESCRIPTION_STRING "Console"
#define SORDI_RDI_PROCVEC Console_AgentRDI
#include "perip_sordi.h"
#include "perip_rdi_agent.h"
IMPLEMENT_AGENT_PROCS_NOEXE_NOMODULE(Console)
IMPLEMENT_AGENT_PROCVEC_NOEXE(Console)
/*--- </> ---*/
/* EOF Console.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -