Exemplo n.º 1
0
void BoardGame::drawBoardLines(QPixmap *cache, QPainter *painter)
{
	float w = cache->width(), h = cache->height();
	float dw, dh;
	float us;
	if (square()) {
		float s = w < h ? w : h;
		dw = (w - s) / 2;
		dh = (h - s) / 2;
		us = (s / size().width());
		if (boardType() != CenterLine)
			us = (int)us;
		w = s;
		h = s;
	} else {
		us = ((w / size().width() < h / size().height() ? w / size().width() : h / size().height()));
		if (boardType() != CenterLine)
			us = (int)us;
		dw = (w - us * size().width()) / 2;
		dh = (h - us * size().height()) / 2;
		w = us * size().width();
		h = us * size().height();
	}
	painter->setPen(COLOR_LINE);
	painter->setBrush(NoBrush);
	for (int r = 0; r < size().height(); r++)
		painter->drawLine((int)(dw + us / 2), (int)(dh + us / 2 + us * r), \
				  (int)(dw + us / 2 + w - us), (int)(dh + us / 2 + us * r));
	for (int c = 0; c < size().height(); c++)
		painter->drawLine((int)(dw + us / 2 + us * c), (int)(dh + us / 2), \
				  (int)(dw + us / 2 + us * c), (int)(dh + us / 2 + h - us));
}
Exemplo n.º 2
0
QRect BoardGame::pointRect(const QSize& disp, const QPoint& point) const
{
	float w = disp.width(), h = disp.height();
	float dw, dh;
	float us;
	if (square()) {
		float s = w < h ? w : h;
		dw = (w - s) / 2;
		dh = (h - s) / 2;
		us = (s / size().width());
		if (boardType() != CenterLine)
			us = (int)us;
		w = s;
		h = s;
	} else {
		us = ((w / size().width() < h / size().height() ? w / size().width() : h / size().height()));
		if (boardType() != CenterLine)
			us = (int)us;
		dw = (w - us * size().width()) / 2;
		dh = (h - us * size().height()) / 2;
		w = us * size().width();
		h = us * size().height();
	}
	int r = point.y(), c = point.x();
	return QRect((int)(dw + us * c), (int)(dh + us * r), (int)us, (int)us);
}
Exemplo n.º 3
0
QPoint BoardGame::findPoint(const QSize& disp, const QPoint& pos)
{
	float w = disp.width(), h = disp.height();
	float dw, dh;
	float us;
	if (square()) {
		float s = w < h ? w : h;
		dw = (w - s) / 2;
		dh = (h - s) / 2;
		us = (s / size().width());
		if (boardType() != CenterLine)
			us = (int)us;
		w = s;
		h = s;
	} else {
		us = ((w / size().width() < h / size().height() ? w / size().width() : h / size().height()));
		if (boardType() != CenterLine)
			us = (int)us;
		dw = (w - us * size().width()) / 2;
		dh = (h - us * size().height()) / 2;
		w = us * size().width();
		h = us * size().height();
	}
	QPoint p((int)(pos.x() - dw), (int)(pos.y() - dh));
	if (p.x() < 0 || p.y() < 0)
		return QPoint(-1, -1);
	p = QPoint((int)(p.x() / us), (int)(p.y() / us));
	if (p.x() >= size().width() || p.y() >= size().height())
		return QPoint(-1, -1);
	return p;
}
Exemplo n.º 4
0
char* AdafruitIO::userAgent()
{
  if(!_user_agent) {
    _user_agent = (char *)malloc(sizeof(char) * (strlen(version()) + strlen(boardType()) + strlen(connectionType()) + 24));
    strcpy(_user_agent, "AdafruitIO-Arduino/");
    strcat(_user_agent, version());
    strcat(_user_agent, " (");
    strcat(_user_agent, boardType());
    strcat(_user_agent, "-");
    strcat(_user_agent, connectionType());
    strcat(_user_agent, ")");
  }
  return _user_agent;
}
Exemplo n.º 5
0
Arquivo: dotstar.c Projeto: TobiBu/POV
// Initialize pins/SPI for output
static PyObject *begin(DotStarObject *self) {
	if(self->dataPin == 0xFF) { // Use hardware SPI
		if((self->fd = open("/dev/spidev0.0", O_RDWR)) < 0) {
			printf("Can't open /dev/spidev0.0 (try 'sudo')\n");
			return NULL;
		}
		uint8_t mode = SPI_MODE_0 | SPI_NO_CS;
		ioctl(self->fd, SPI_IOC_WR_MODE, &mode);
		// The actual data rate may be less than requested.
		// Hardware SPI speed is a function of the system core
		// frequency and the smallest power-of-two prescaler
		// that will not exceed the requested rate.
		// e.g. 8 MHz request: 250 MHz / 32 = 7.8125 MHz.
		ioctl(self->fd, SPI_IOC_WR_MAX_SPEED_HZ, self->bitrate);
		xfer[0].tx_buf = (unsigned long)header;
		xfer[2].tx_buf = (unsigned long)footer;
		xfer[0].speed_hz = xfer[1].speed_hz = xfer[2].speed_hz =
		  self->bitrate;
	} else { // Use bitbang "soft" SPI (any 2 pins)
		if(gpio == NULL) { // First time accessing GPIO?
			int fd;

			if((fd = open("/dev/mem", O_RDWR | O_SYNC)) < 0) {
				printf("Can't open /dev/mem (try 'sudo')\n");
				return NULL;
			}
			isPi2 = (boardType() == 2);
			gpio  = (volatile unsigned *)mmap( // Memory-map I/O
			  NULL,                 // Any adddress will do
			  BLOCK_SIZE,           // Mapped block length
			  PROT_READ|PROT_WRITE, // Enable read+write
			  MAP_SHARED,           // Shared w/other processes
			  fd,                   // File to map
			  isPi2 ?
			   PI2_GPIO_BASE :      // -> GPIO registers
			   PI1_GPIO_BASE);
			close(fd);              // Not needed after mmap()
			if(gpio == MAP_FAILED) {
				err("Can't mmap()");
				return NULL;
			}
			gpioSet = &gpio[7];
			gpioClr = &gpio[10];
		}

		self->dataMask  = 1 << self->dataPin;
		self->clockMask = 1 << self->clockPin;

		// Set 2 pins as outputs.  Must use INP before OUT.
		INP_GPIO(self->dataPin);  OUT_GPIO(self->dataPin);
		INP_GPIO(self->clockPin); OUT_GPIO(self->clockPin);

		*gpioClr = self->dataMask | self->clockMask; // data+clock LOW
	}

	Py_INCREF(Py_None);
	return Py_None;
}
Exemplo n.º 6
0
void BoardGame::hoverPixmap(QPixmap *cache, QPixmap *hover, const int player)
{
	QRect rect = pointRect(cache->size(), QPoint(0, 0));
	hover->resize(rect.size());
	QPainter painter(hover);
	drawHover(hover, &painter, player);
	if (boardType() != EdgeLine)
		return;
	painter.setPen(COLOR_LINE);
	painter.setBrush(NoBrush);
	painter.drawRect(hover->rect());
}
Exemplo n.º 7
0
void BoardGame::refresh(QPixmap *cache)
{
	if (gameName() == BoardGame::gameName()) {
		QPainter painter(cache);
		painter.setPen(NoPen);
		painter.setBrush(QBrush(white));
		painter.drawRect(cache->rect());
		painter.setPen(QPen(COLOR_LINE, 10));
		painter.setBrush(QBrush(COLOR_BOARD));
		painter.drawEllipse(cache->rect());
		QFont f("noah", 24);
		painter.setFont(f);
		painter.drawText(cache->rect(), AlignCenter, tr("Board Games!"));
		return;
	}
/*	generalRefresh(cache);
}

void BoardGame::generalRefresh(QPixmap *cache)
{*/
	QPainter painter(cache);
	drawBackground(cache, &painter);
	switch (boardType()) {
	case CenterLine:
		drawBoardLines(cache, &painter);
	case NoLine:
		break;
	case EdgeLine:
		drawEdgeLines(cache, &painter);
	}
	for (int r = 0; r < size().height(); r++)
		for (int c = 0; c < size().width(); c++)
			drawPoint(cache, &painter, QPoint(c, r), data.pos[r][c]);
	if (data.last.x() != -1)
		drawLast(cache, &painter, data.last, DATA(data.last));
}
Exemplo n.º 8
0
void Init_ODM_ComInfo(_adapter *adapter)
{
	struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(adapter);
	EEPROM_EFUSE_PRIV	*pEEPROM = GET_EEPROM_EFUSE_PRIV(adapter);
	struct dm_priv	*pdmpriv = &pHalData->dmpriv;
	PDM_ODM_T		pDM_Odm = &(pHalData->odmpriv);
	struct mlme_ext_priv	*pmlmeext = &adapter->mlmeextpriv;
	struct mlme_priv	*pmlmepriv = &adapter->mlmepriv;
	struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(adapter);
	int i;

	_rtw_memset(pDM_Odm,0,sizeof(*pDM_Odm));

	pDM_Odm->Adapter = adapter;

	ODM_CmnInfoInit(pDM_Odm, ODM_CMNINFO_PLATFORM, ODM_CE);

	if (adapter->interface_type == RTW_GSPI)
		ODM_CmnInfoInit(pDM_Odm, ODM_CMNINFO_INTERFACE, ODM_ITRF_SDIO);
	else
		ODM_CmnInfoInit(pDM_Odm, ODM_CMNINFO_INTERFACE, adapter->interface_type);

	ODM_CmnInfoInit(pDM_Odm, ODM_CMNINFO_MP_TEST_CHIP, IS_NORMAL_CHIP(pHalData->VersionID));

	ODM_CmnInfoInit(pDM_Odm, ODM_CMNINFO_PATCH_ID, pEEPROM->CustomerID);

	ODM_CmnInfoInit(pDM_Odm, ODM_CMNINFO_BWIFI_TEST, adapter->registrypriv.wifi_spec);

	if (pHalData->rf_type == RF_1T1R) {
		ODM_CmnInfoUpdate(pDM_Odm, ODM_CMNINFO_RF_TYPE, ODM_1T1R);
	}
	else if (pHalData->rf_type == RF_2T2R){
		ODM_CmnInfoUpdate(pDM_Odm, ODM_CMNINFO_RF_TYPE, ODM_2T2R);
	}
	else if (pHalData->rf_type == RF_1T2R){
		ODM_CmnInfoUpdate(pDM_Odm, ODM_CMNINFO_RF_TYPE, ODM_1T2R);
	}

{
	//1 ======= BoardType: ODM_CMNINFO_BOARD_TYPE =======
	u8 odm_board_type = ODM_BOARD_DEFAULT;

	if (!IS_HARDWARE_TYPE_OLDER_THAN_8723A(adapter))
	{
		if (pHalData->ExternalLNA_2G != 0) {
			odm_board_type |= ODM_BOARD_EXT_LNA;
			ODM_CmnInfoInit(pDM_Odm, ODM_CMNINFO_EXT_LNA, 1);
		}
		if (pHalData->ExternalLNA_5G != 0) {
			odm_board_type |= ODM_BOARD_EXT_LNA_5G;
			ODM_CmnInfoInit(pDM_Odm, ODM_CMNINFO_5G_EXT_LNA, 1);
		}
		if (pHalData->ExternalPA_2G != 0) {
			odm_board_type |= ODM_BOARD_EXT_PA;
			ODM_CmnInfoInit(pDM_Odm, ODM_CMNINFO_EXT_PA, 1);
		}
		if (pHalData->ExternalPA_5G != 0) {
			odm_board_type |= ODM_BOARD_EXT_PA_5G;
			ODM_CmnInfoInit(pDM_Odm, ODM_CMNINFO_5G_EXT_PA, 1);
		}
		if (pHalData->EEPROMBluetoothCoexist)
			odm_board_type |= ODM_BOARD_BT;

	} else {
		#ifdef CONFIG_USB_HCI
		if (pHalData->InterfaceSel == INTF_SEL1_USB_High_Power
			|| pHalData->BoardType == BOARD_USB_High_PA	/* This is legacy code for hal_data.BoardType */
		) {
			ODM_CmnInfoInit(pDM_Odm,ODM_CMNINFO_EXT_LNA, 1);
			ODM_CmnInfoInit(pDM_Odm,ODM_CMNINFO_EXT_PA, 1);
		} else
		#endif
		{
			ODM_CmnInfoInit(pDM_Odm, ODM_CMNINFO_EXT_PA, pHalData->ExternalPA_2G);
			ODM_CmnInfoInit(pDM_Odm, ODM_CMNINFO_EXT_LNA, pHalData->ExternalLNA_2G);
		}

		odm_board_type = boardType(pHalData->InterfaceSel);
	}

	ODM_CmnInfoInit(pDM_Odm, ODM_CMNINFO_BOARD_TYPE, odm_board_type);
	//1 ============== End of BoardType ==============
}

	ODM_CmnInfoInit(pDM_Odm, ODM_CMNINFO_DOMAIN_CODE_2G, pHalData->Regulation2_4G);
	ODM_CmnInfoInit(pDM_Odm, ODM_CMNINFO_DOMAIN_CODE_5G, pHalData->Regulation5G);

	ODM_CmnInfoInit(pDM_Odm, ODM_CMNINFO_GPA, pHalData->TypeGPA);
	ODM_CmnInfoInit(pDM_Odm, ODM_CMNINFO_APA, pHalData->TypeAPA);
	ODM_CmnInfoInit(pDM_Odm, ODM_CMNINFO_GLNA, pHalData->TypeGLNA);
	ODM_CmnInfoInit(pDM_Odm, ODM_CMNINFO_ALNA, pHalData->TypeALNA);

	ODM_CmnInfoInit(pDM_Odm, ODM_CMNINFO_RFE_TYPE, pHalData->RFEType);

	ODM_CmnInfoInit(pDM_Odm, ODM_CMNINFO_EXT_TRSW, 0);

	/* Pointer reference */
	ODM_CmnInfoHook(pDM_Odm, ODM_CMNINFO_TX_UNI, &(dvobj->traffic_stat.tx_bytes));
	ODM_CmnInfoHook(pDM_Odm, ODM_CMNINFO_RX_UNI, &(dvobj->traffic_stat.rx_bytes));
	ODM_CmnInfoHook(pDM_Odm, ODM_CMNINFO_WM_MODE, &(pmlmeext->cur_wireless_mode));
	ODM_CmnInfoHook(pDM_Odm, ODM_CMNINFO_BAND, &(pHalData->CurrentBandType));
	ODM_CmnInfoHook(pDM_Odm, ODM_CMNINFO_FORCED_RATE, &(pHalData->ForcedDataRate));

	ODM_CmnInfoHook(pDM_Odm, ODM_CMNINFO_SEC_CHNL_OFFSET, &(pHalData->nCur40MhzPrimeSC));
	ODM_CmnInfoHook(pDM_Odm, ODM_CMNINFO_SEC_MODE, &(adapter->securitypriv.dot11PrivacyAlgrthm));
	ODM_CmnInfoHook(pDM_Odm, ODM_CMNINFO_BW, &(pHalData->CurrentChannelBW));
	ODM_CmnInfoHook(pDM_Odm, ODM_CMNINFO_CHNL, &( pHalData->CurrentChannel));
	ODM_CmnInfoHook(pDM_Odm, ODM_CMNINFO_NET_CLOSED, &(adapter->net_closed));
	ODM_CmnInfoHook(pDM_Odm, ODM_CMNINFO_FORCED_IGI_LB, &(pHalData->u1ForcedIgiLb));

	ODM_CmnInfoHook(pDM_Odm, ODM_CMNINFO_SCAN, &(pmlmepriv->bScanInProcess));
	ODM_CmnInfoHook(pDM_Odm, ODM_CMNINFO_POWER_SAVING, &(pwrctl->bpower_saving));

	for(i=0; i<ODM_ASSOCIATE_ENTRY_NUM; i++)
		ODM_CmnInfoPtrArrayHook(pDM_Odm, ODM_CMNINFO_STA_STATUS, i, NULL);

	/* TODO */
	//ODM_CmnInfoHook(pDM_Odm, ODM_CMNINFO_BT_OPERATION, _FALSE);
	//ODM_CmnInfoHook(pDM_Odm, ODM_CMNINFO_BT_DISABLE_EDCA, _FALSE);
}
int main(int argc, char *argv[]) {

	// A few arrays here are declared with 32 elements, even though
	// values aren't needed for io[] members where the 'key' value is
	// GND.  This simplifies the code a bit -- no need for mallocs and
	// tests to create these arrays -- but may waste a handful of
	// bytes for any declared GNDs.
	char                   buf[50],      // For sundry filenames
	                       c,            // Pin input value ('0'/'1')
	                       board;        // 0=Pi1Rev1, 1=Pi1Rev2, 2=Pi2
	int                    fd,           // For mmap, sysfs, uinput
	                       i, j,         // Asst. counter
	                       bitmask,      // Pullup enable bitmask
	                       timeout = -1, // poll() timeout
	                       intstate[32], // Last-read state
	                       extstate[32], // Debounced state
	                       lastKey = -1; // Last key down (for repeat)
	unsigned long          bitMask, bit; // For Vulcan pinch detect
	volatile unsigned char shortWait;    // Delay counter
	struct input_event     keyEv, synEv; // uinput events
	struct pollfd          p[32];        // GPIO file descriptors

	progName = argv[0];             // For error reporting
	signal(SIGINT , signalHandler); // Trap basic signals (exit cleanly)
	signal(SIGKILL, signalHandler);

//not needed
/*
	// Select io[] table for Cupcade (TFT) or 'normal' project.
	io = (access("/etc/modprobe.d/adafruit.conf", F_OK) ||
	      access("/dev/fb1", F_OK)) ? ioStandard : ioTFT;
*/
	io = ioStandard;
	// If this is a "Revision 1" Pi board (no mounting holes),
	// remap certain pin numbers in the io[] array for compatibility.
	// This way the code doesn't need modification for old boards.
	board = boardType();
	if(board == 0) {
		for(i=0; io[i].pin >= 0; i++) {
			if(     io[i].pin ==  2) io[i].pin = 0;
			else if(io[i].pin ==  3) io[i].pin = 1;
			else if(io[i].pin == 27) io[i].pin = 21;
		}
	}

	// ----------------------------------------------------------------
	// Although Sysfs provides solid GPIO interrupt handling, there's
	// no interface to the internal pull-up resistors (this is by
	// design, being a hardware-dependent feature).  It's necessary to
	// grapple with the GPIO configuration registers directly to enable
	// the pull-ups.  Based on GPIO example code by Dom and Gert van
	// Loo on elinux.org

	if((fd = open("/dev/mem", O_RDWR | O_SYNC)) < 0)
		err("Can't open /dev/mem");
	gpio = mmap(            // Memory-mapped I/O
	  NULL,                 // Any adddress will do
	  BLOCK_SIZE,           // Mapped block length
	  PROT_READ|PROT_WRITE, // Enable read+write
	  MAP_SHARED,           // Shared with other processes
	  fd,                   // File to map
	  (board == 2) ?
	   PI2_GPIO_BASE :      // -> GPIO registers
	   PI1_GPIO_BASE);

	close(fd);              // Not needed after mmap()
	if(gpio == MAP_FAILED) err("Can't mmap()");
	// Make combined bitmap of pullup-enabled pins:
	for(bitmask=i=0; io[i].pin >= 0; i++)
		if(io[i].key != GND) bitmask |= (1 << io[i].pin);
	gpio[GPPUD]     = 2;                    // Enable pullup
	for(shortWait=150;--shortWait;);        // Min 150 cycle wait
	gpio[GPPUDCLK0] = bitmask;              // Set pullup mask
	for(shortWait=150;--shortWait;);        // Wait again
	gpio[GPPUD]     = 0;                    // Reset pullup registers
	gpio[GPPUDCLK0] = 0;
	(void)munmap((void *)gpio, BLOCK_SIZE); // Done with GPIO mmap()


	// ----------------------------------------------------------------
	// All other GPIO config is handled through the sysfs interface.

	sprintf(buf, "%s/export", sysfs_root);
	if((fd = open(buf, O_WRONLY)) < 0) // Open Sysfs export file
		err("Can't open GPIO export file");
	for(i=j=0; io[i].pin >= 0; i++) { // For each pin of interest...
		sprintf(buf, "%d", io[i].pin);
		write(fd, buf, strlen(buf));             // Export pin
		pinConfig(io[i].pin, "active_low", "0"); // Don't invert
		if(io[i].key == GND) {
			// Set pin to output, value 0 (ground)
			if(pinConfig(io[i].pin, "direction", "out") ||
			   pinConfig(io[i].pin, "value"    , "0"))
				err("Pin config failed (GND)");
		} else {
			// Set pin to input, detect rise+fall events
			if(pinConfig(io[i].pin, "direction", "in") ||
			   pinConfig(io[i].pin, "edge"     , "both"))
				err("Pin config failed");
			// Get initial pin value
			sprintf(buf, "%s/gpio%d/value",
			  sysfs_root, io[i].pin);
			// The p[] file descriptor array isn't necessarily
			// aligned with the io[] array.  GND keys in the
			// latter are skipped, but p[] requires contiguous
			// entries for poll().  So the pins to monitor are
			// at the head of p[], and there may be unused
			// elements at the end for each GND.  Same applies
			// to the intstate[] and extstate[] arrays.
			if((p[j].fd = open(buf, O_RDONLY)) < 0)
				err("Can't access pin value");
			intstate[j] = 0;
			if((read(p[j].fd, &c, 1) == 1) && (c == '0'))
				intstate[j] = 1;
			extstate[j] = intstate[j];
			p[j].events  = POLLPRI; // Set up poll() events
			p[j].revents = 0;
			j++;
		}
	} // 'j' is now count of non-GND items in io[] table
	close(fd); // Done exporting


	// ----------------------------------------------------------------
	// Set up uinput

#if 1
	// Retrogame normally uses /dev/uinput for generating key events.
	// Cupcade requires this and it's the default.  SDL2 (used by
	// some newer emulators) doesn't like it, wants /dev/input/event0
	// instead.  Enable that code by changing to "#if 0" above.
	if((fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK)) < 0)
		err("Can't open /dev/uinput");
	if(ioctl(fd, UI_SET_EVBIT, EV_KEY) < 0)
		err("Can't SET_EVBIT");
	for(i=0; io[i].pin >= 0; i++) {
		if(io[i].key != GND) {
			if(ioctl(fd, UI_SET_KEYBIT, io[i].key) < 0)
				err("Can't SET_KEYBIT");
		}
	}
	if(ioctl(fd, UI_SET_KEYBIT, vulcanKey) < 0) err("Can't SET_KEYBIT");
	struct uinput_user_dev uidev;
	memset(&uidev, 0, sizeof(uidev));
	snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, "retrogame");
	uidev.id.bustype = BUS_USB;
	uidev.id.vendor  = 0x1;
	uidev.id.product = 0x1;
	uidev.id.version = 1;
	if(write(fd, &uidev, sizeof(uidev)) < 0)
		err("write failed");
	if(ioctl(fd, UI_DEV_CREATE) < 0)
		err("DEV_CREATE failed");
#else // SDL2 prefers this event methodology
	if((fd = open("/dev/input/event0", O_WRONLY | O_NONBLOCK)) < 0)
		err("Can't open /dev/input/event0");
#endif

	// Initialize input event structures
	memset(&keyEv, 0, sizeof(keyEv));
	keyEv.type  = EV_KEY;
	memset(&synEv, 0, sizeof(synEv));
	synEv.type  = EV_SYN;
	synEv.code  = SYN_REPORT;
	synEv.value = 0;

	// 'fd' is now open file descriptor for issuing uinput events


	// ----------------------------------------------------------------
	// Monitor GPIO file descriptors for button events.  The poll()
	// function watches for GPIO IRQs in this case; it is NOT
	// continually polling the pins!  Processor load is near zero.

	while(running) { // Signal handler can set this to 0 to exit
		// Wait for IRQ on pin (or timeout for button debounce)
		if(poll(p, j, timeout) > 0) { // If IRQ...
			for(i=0; i<j; i++) {       // Scan non-GND pins...
				if(p[i].revents) { // Event received?
					// Read current pin state, store
					// in internal state flag, but
					// don't issue to uinput yet --
					// must wait for debounce!
					lseek(p[i].fd, 0, SEEK_SET);
					read(p[i].fd, &c, 1);
					if(c == '0')      intstate[i] = 1;
					else if(c == '1') intstate[i] = 0;
					p[i].revents = 0; // Clear flag
				}
			}
			timeout = debounceTime; // Set timeout for debounce
			c       = 0;            // Don't issue SYN event
			// Else timeout occurred
		} else if(timeout == debounceTime) { // Button debounce timeout
			// 'j' (number of non-GNDs) is re-counted as
			// it's easier than maintaining an additional
			// remapping table or a duplicate key[] list.
			bitMask = 0L; // Mask of buttons currently pressed
			bit     = 1L;
			for(c=i=j=0; io[i].pin >= 0; i++, bit<<=1) {
				if(io[i].key != GND) {
					// Compare internal state against
					// previously-issued value.  Send
					// keystrokes only for changed states.
					if(intstate[j] != extstate[j]) {
						extstate[j] = intstate[j];
						keyEv.code  = io[i].key;
						keyEv.value = intstate[j];
						if ((keyEv.code==KEY_0)&&(keyEv.value==1))
						{
							system("sudo halt");
							//system("echo \"that works\"");
						}
						else
						{
							write(fd, &keyEv,
							sizeof(keyEv));
						}
						//write(fd, &keyEv,
						//sizeof(keyEv));
						c = 1; // Follow w/SYN event
						if(intstate[j]) { // Press?
							// Note pressed key
							// and set initial
							// repeat interval.
							lastKey = i;
							timeout = repTime1;
						} else { // Release?
							// Stop repeat and
							// return to normal
							// IRQ monitoring
							// (no timeout).
							lastKey = timeout = -1;
						}
					}
					j++;
					if(intstate[i]) bitMask |= bit;
				}
			}

			// If the "Vulcan nerve pinch" buttons are pressed,
			// set long timeout -- if this time elapses without
			// a button state change, esc keypress will be sent.
			if((bitMask & vulcanMask) == vulcanMask)
				timeout = vulcanTime;
		} else if(timeout == vulcanTime) { // Vulcan timeout occurred
			// Send keycode (MAME exits or displays exit menu)
			keyEv.code = vulcanKey;
			for(i=1; i>= 0; i--) { // Press, release
				keyEv.value = i;
				write(fd, &keyEv, sizeof(keyEv));
				usleep(10000); // Be slow, else MAME flakes
				write(fd, &synEv, sizeof(synEv));
				usleep(10000);
			}
			timeout = -1; // Return to normal processing
			c       = 0;  // No add'l SYN required
		} else if(lastKey >= 0) { // Else key repeat timeout
			if(timeout == repTime1) timeout = repTime2;
			else if(timeout > 30)   timeout -= 5; // Accelerate
			c           = 1; // Follow w/SYN event
			keyEv.code  = io[lastKey].key;
			keyEv.value = 2; // Key repeat event
			write(fd, &keyEv, sizeof(keyEv));
		}
		if(c) write(fd, &synEv, sizeof(synEv));
	}

	// ----------------------------------------------------------------
	// Clean up

	ioctl(fd, UI_DEV_DESTROY); // Destroy and
	close(fd);                 // close uinput
	cleanup();                 // Un-export pins

	puts("Done.");

	return 0;
}