/* * Mach Operating System * Copyright (c) 1991,1990,1989 Carnegie Mellon University * All Rights Reserved. * * Permission to use, copy, modify and distribute this software and its * documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. * * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. * * Carnegie Mellon requests users of this software to return to * * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU * School of Computer Science * Carnegie Mellon University * Pittsburgh PA 15213-3890 * * any improvements or extensions that they make and grant Carnegie Mellon * the rights to redistribute these changes. */ /* * File: bt431.c * Author: Alessandro Forin, Carnegie Mellon University * Date: 8/91 * * Routines for the bt431 Cursor */ #include #include #include #ifdef DECSTATION /* * This configuration uses two twin 431s */ #define set_value(x) (((x)<<8)|((x)&0xff)) #define get_value(x) ((x)&0xff) typedef struct { volatile unsigned short addr_lo; short pad0; volatile unsigned short addr_hi; short pad1; volatile unsigned short addr_cmap; short pad2; volatile unsigned short addr_reg; short pad3; } bt431_padded_regmap_t; #else /*DECSTATION*/ #define set_value(x) x #define get_value(x) x typedef bt431_regmap_t bt431_padded_regmap_t; #define wbflush() #endif /*DECSTATION*/ /* * Generic register access */ void bt431_select_reg( regs, regno) bt431_padded_regmap_t *regs; { regs->addr_lo = set_value(regno&0xff); regs->addr_hi = set_value((regno >> 8) & 0xff); wbflush(); } void bt431_write_reg( regs, regno, val) bt431_padded_regmap_t *regs; { bt431_select_reg( regs, regno ); regs->addr_reg = set_value(val); wbflush(); } unsigned char bt431_read_reg( regs, regno) bt431_padded_regmap_t *regs; { bt431_select_reg( regs, regno ); return get_value(regs->addr_reg); } /* when using autoincrement */ #define bt431_write_reg_autoi( regs, regno, val) \ { \ (regs)->addr_reg = set_value(val); \ wbflush(); \ } #define bt431_read_reg_autoi( regs, regno) \ get_value(((regs)->addr_reg)) #define bt431_write_cmap_autoi( regs, regno, val) \ { \ (regs)->addr_cmap = (val); \ wbflush(); \ } #define bt431_read_cmap_autoi( regs, regno) \ ((regs)->addr_cmap) /* * Cursor ops */ bt431_cursor_on(regs) bt431_padded_regmap_t *regs; { bt431_write_reg( regs, BT431_REG_CMD, BT431_CMD_CURS_ENABLE|BT431_CMD_OR_CURSORS| BT431_CMD_4_1_MUX|BT431_CMD_THICK_1); } bt431_cursor_off(regs) bt431_padded_regmap_t *regs; { bt431_write_reg( regs, BT431_REG_CMD, BT431_CMD_4_1_MUX); } bt431_pos_cursor(regs,x,y) bt431_padded_regmap_t *regs; register int x,y; { #define lo(v) ((v)&0xff) #define hi(v) (((v)&0xf00)>>8) /* * Cx = x + D + H - P * P = 37 if 1:1, 52 if 4:1, 57 if 5:1 * D = pixel skew between outdata and external data * H = pixels between HSYNCH falling and active video * * Cy = y + V - 32 * V = scanlines between HSYNCH falling, two or more * clocks after VSYNCH falling, and active video */ bt431_write_reg( regs, BT431_REG_CXLO, lo(x + 360)); /* use autoincr feature */ bt431_write_reg_autoi( regs, BT431_REG_CXHI, hi(x + 360)); bt431_write_reg_autoi( regs, BT431_REG_CYLO, lo(y + 36)); bt431_write_reg_autoi( regs, BT431_REG_CYHI, hi(y + 36)); } bt431_cursor_sprite( regs, cursor) bt431_padded_regmap_t *regs; register unsigned short *cursor; { register int i; bt431_select_reg( regs, BT431_REG_CRAM_BASE+0); for (i = 0; i < 512; i++) bt431_write_cmap_autoi( regs, BT431_REG_CRAM_BASE+i, *cursor++); } #if 1 bt431_print_cursor(regs) bt431_padded_regmap_t *regs; { unsigned short curs[512]; register int i; bt431_select_reg( regs, BT431_REG_CRAM_BASE+0); for (i = 0; i < 512; i++) { curs[i] = bt431_read_cmap_autoi( regs, BT431_REG_CRAM_BASE+i); } for (i = 0; i < 512; i += 16) printf("%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x\n", curs[i], curs[i+1], curs[i+2], curs[i+3], curs[i+4], curs[i+5], curs[i+6], curs[i+7], curs[i+8], curs[i+9], curs[i+10], curs[i+11], curs[i+12], curs[i+13], curs[i+14], curs[i+15]); } #endif /* * Initialization */ unsigned /*char*/short bt431_default_cursor[64*8] = { 0xffff, 0, 0, 0, 0, 0, 0, 0, 0xffff, 0, 0, 0, 0, 0, 0, 0, 0xffff, 0, 0, 0, 0, 0, 0, 0, 0xffff, 0, 0, 0, 0, 0, 0, 0, 0xffff, 0, 0, 0, 0, 0, 0, 0, 0xffff, 0, 0, 0, 0, 0, 0, 0, 0xffff, 0, 0, 0, 0, 0, 0, 0, 0xffff, 0, 0, 0, 0, 0, 0, 0, 0xffff, 0, 0, 0, 0, 0, 0, 0, 0xffff, 0, 0, 0, 0, 0, 0, 0, 0xffff, 0, 0, 0, 0, 0, 0, 0, 0xffff, 0, 0, 0, 0, 0, 0, 0, 0xffff, 0, 0, 0, 0, 0, 0, 0, 0xffff, 0, 0, 0, 0, 0, 0, 0, 0xffff, 0, 0, 0, 0, 0, 0, 0, 0xffff, 0, 0, 0, 0, 0, 0, 0, 0, }; bt431_init(regs) bt431_padded_regmap_t *regs; { register int i; /* use 4:1 input mux */ bt431_write_reg( regs, BT431_REG_CMD, BT431_CMD_CURS_ENABLE|BT431_CMD_OR_CURSORS| BT431_CMD_4_1_MUX|BT431_CMD_THICK_1); /* home cursor */ bt431_write_reg_autoi( regs, BT431_REG_CXLO, 0x00); bt431_write_reg_autoi( regs, BT431_REG_CXHI, 0x00); bt431_write_reg_autoi( regs, BT431_REG_CYLO, 0x00); bt431_write_reg_autoi( regs, BT431_REG_CYHI, 0x00); /* no crosshair window */ bt431_write_reg_autoi( regs, BT431_REG_WXLO, 0x00); bt431_write_reg_autoi( regs, BT431_REG_WXHI, 0x00); bt431_write_reg_autoi( regs, BT431_REG_WYLO, 0x00); bt431_write_reg_autoi( regs, BT431_REG_WYHI, 0x00); bt431_write_reg_autoi( regs, BT431_REG_WWLO, 0x00); bt431_write_reg_autoi( regs, BT431_REG_WWHI, 0x00); bt431_write_reg_autoi( regs, BT431_REG_WHLO, 0x00); bt431_write_reg_autoi( regs, BT431_REG_WHHI, 0x00); /* load default cursor */ bt431_cursor_sprite( regs, bt431_default_cursor); }