⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 console.c

📁 ARMULATOR的原代码AR MULATOR的原代码ARMULATOR的原代码
💻 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 + -