Example #1
0
void cdc_control_poll(void) {
  // flush out queue every now and then
  if(flush_timer && CheckTimer(flush_timer)) {
    cdc_control_flush();
    flush_timer = 0;
  }

  // low level usb handling happens inside usb_cdc_poll
  if(usb_cdc_poll()) {
    uint16_t read, i;
    char data[AT91C_EP_OUT_SIZE];

    // check for user input
    if((read = usb_cdc_read(data, AT91C_EP_OUT_SIZE)) != 0) {
      
      switch(tos_get_cdc_control_redirect()) {
      case CDC_REDIRECT_RS232:
	iprintf("RS232 forward:\n");
	hexdump(data, read, 0);

	user_io_serial_tx(data, read);
	break;
	
      case CDC_REDIRECT_CONTROL:
	for(i=0;i<read;i++) {
	  // force lower case
	  if((data[i] >= 'A') && (data[i] <= 'Z'))
	    data[i] = data[i] - 'A' + 'a';
	  
	  switch(data[i]) {
	  case '\r':
	    cdc_puts("\n\033[7m <<< MIST board controller >>> \033[0m");
	    cdc_puts("Firmware version ATH" VDATE);
	    cdc_puts("Commands:");
	    cdc_puts("\033[7mR\033[0meset");
	    cdc_puts("\033[7mC\033[0moldreset");
	    cdc_puts("\033[7mD\033[0mebug output redirect");
	    cdc_puts("R\033[7mS\033[0m232 redirect");
	    cdc_puts("\033[7mP\033[0marallel redirect");
	    cdc_puts("\033[7mM\033[0mIDI redirect");
	    cdc_puts("");
	    break;
	    
	  case 'r':
	    cdc_puts("Reset ...");
	    tos_reset(0);
	    break;
	    
	  case 'c':
	    cdc_puts("Coldreset ...");
	    tos_reset(1);
	    break;
	    
	  case 'd':
	    cdc_puts("Debug output redirect enabled");
	    tos_set_cdc_control_redirect(CDC_REDIRECT_DEBUG);
	    break;
	    
	  case 's':
	    cdc_puts("RS232 redirect enabled");
	    tos_set_cdc_control_redirect(CDC_REDIRECT_RS232);
	    break;
	    
	  case 'p':
	    cdc_puts("Parallel redirect enabled");
	    tos_set_cdc_control_redirect(CDC_REDIRECT_PARALLEL);
	    break;
	    
	  case 'm':
	    cdc_puts("MIDI redirect enabled");
	    tos_set_cdc_control_redirect(CDC_REDIRECT_MIDI);
	    break;
	    
	  }
	  break;
	}
  
	default:
	  break;
      }
    }
  }
}
Example #2
0
void user_io_poll() {

  if(user_io_dip_switch1()) {
    // check of core has changed from a good one to a not supported on
    // as this likely means that the user is reloading the core via jtag
    unsigned char ct;
    static unsigned char ct_cnt = 0;
    
    EnableIO();
    ct = SPI(0xff);
    DisableIO();
    SPI(0xff);      // needed for old minimig core
    
    if(ct == core_type) 
      ct_cnt = 0;        // same core type, everything is fine
    else {
      // core type has changed
      if(++ct_cnt == 255) {
	// wait for a new valid core id to appear
	while((ct &  0xf0) != 0xa0) {
	  EnableIO();
	  ct = SPI(0xff);
	  DisableIO();
	  SPI(0xff);      // needed for old minimig core
	}

	// reset io controller to cope with new core
	*AT91C_RSTC_RCR = 0xA5 << 24 | AT91C_RSTC_PERRST | AT91C_RSTC_PROCRST; // restart
	for(;;);
      }
    }
  }

  if((core_type != CORE_TYPE_MINIMIG) &&
     (core_type != CORE_TYPE_MINIMIG2) &&
     (core_type != CORE_TYPE_PACE) &&
     (core_type != CORE_TYPE_MIST) &&
     (core_type != CORE_TYPE_ARCHIE) &&
     (core_type != CORE_TYPE_8BIT)) {
    return;  // no user io for the installed core
  }

  if(core_type == CORE_TYPE_MIST) {
    char redirect = tos_get_cdc_control_redirect();

    ikbd_poll();

    // check for input data on usart
    USART_Poll();
      
    unsigned char c = 0;

    // check for incoming serial data. this is directly forwarded to the
    // arm rs232 and mixes with debug output. Useful for debugging only of
    // e.g. the diagnostic cartridge    
    if(!pl2303_is_blocked()) {
      spi_uio_cmd_cont(UIO_SERIAL_IN);
      while(spi_in() && !pl2303_is_blocked()) {
	c = spi_in();
	
	// if a serial/usb adapter is connected it has precesence over
	// any other sink
	if(pl2303_present()) 
	  pl2303_tx_byte(c);
	else {
	  if(c != 0xff) 
	    putchar(c);
	  
	  // forward to USB if redirection via USB/CDC enabled
	  if(redirect == CDC_REDIRECT_RS232)
	    cdc_control_tx(c);
	}
      }
      DisableIO();
    }
    
    // check for incoming parallel/midi data
    if((redirect == CDC_REDIRECT_PARALLEL) || (redirect == CDC_REDIRECT_MIDI)) {
      spi_uio_cmd_cont((redirect == CDC_REDIRECT_PARALLEL)?UIO_PARALLEL_IN:UIO_MIDI_IN);
      // character 0xff is returned if FPGA isn't configured
      c = 0;
      while(spi_in() && (c!= 0xff)) {
	c = spi_in();
	cdc_control_tx(c);
      }
      DisableIO();
      
      // always flush when doing midi to reduce latencies
      if(redirect == CDC_REDIRECT_MIDI)
	cdc_control_flush();
    }
  }

  // poll db9 joysticks
  static int joy0_state = JOY0;
  if((*AT91C_PIOA_PDSR & JOY0) != joy0_state) {
    joy0_state = *AT91C_PIOA_PDSR & JOY0;
    
    unsigned char joy_map = 0;
    if(!(joy0_state & JOY0_UP))    joy_map |= JOY_UP;
    if(!(joy0_state & JOY0_DOWN))  joy_map |= JOY_DOWN;
    if(!(joy0_state & JOY0_LEFT))  joy_map |= JOY_LEFT;
    if(!(joy0_state & JOY0_RIGHT)) joy_map |= JOY_RIGHT;
    if(!(joy0_state & JOY0_BTN1))  joy_map |= JOY_BTN1;
    if(!(joy0_state & JOY0_BTN2))  joy_map |= JOY_BTN2;

    user_io_joystick(joystick_renumber(0), joy_map);
  }
  
  static int joy1_state = JOY1;
  if((*AT91C_PIOA_PDSR & JOY1) != joy1_state) {
    joy1_state = *AT91C_PIOA_PDSR & JOY1;
    
    unsigned char joy_map = 0;
    if(!(joy1_state & JOY1_UP))    joy_map |= JOY_UP;
    if(!(joy1_state & JOY1_DOWN))  joy_map |= JOY_DOWN;
    if(!(joy1_state & JOY1_LEFT))  joy_map |= JOY_LEFT;
    if(!(joy1_state & JOY1_RIGHT)) joy_map |= JOY_RIGHT;
    if(!(joy1_state & JOY1_BTN1))  joy_map |= JOY_BTN1;
    if(!(joy1_state & JOY1_BTN2))  joy_map |= JOY_BTN2;
    
    user_io_joystick(joystick_renumber(1), joy_map);
  }

  user_io_send_buttons(0);

  // mouse movement emulation is continous 
  if(emu_mode == EMU_MOUSE) {
    if(CheckTimer(emu_timer)) {
      emu_timer = GetTimer(EMU_MOUSE_FREQ);
      
      if(emu_state & JOY_MOVE) {
	unsigned char b = 0;
	char x = 0, y = 0;
	if((emu_state & (JOY_LEFT | JOY_RIGHT)) == JOY_LEFT)  x = -1; 
	if((emu_state & (JOY_LEFT | JOY_RIGHT)) == JOY_RIGHT) x = +1; 
	if((emu_state & (JOY_UP   | JOY_DOWN))  == JOY_UP)    y = -1; 
	if((emu_state & (JOY_UP   | JOY_DOWN))  == JOY_DOWN)  y = +1; 
	
	if(emu_state & JOY_BTN1) b |= 1;
	if(emu_state & JOY_BTN2) b |= 2;
	
	user_io_mouse(b, x, y);
      }
    }
  }

  if((core_type == CORE_TYPE_MINIMIG) ||
     (core_type == CORE_TYPE_MINIMIG2)) {
    kbd_fifo_poll();

    // frequently check mouse for events
    if(CheckTimer(mouse_timer)) {
      mouse_timer = GetTimer(MOUSE_FREQ);

      // has ps2 mouse data been updated in the meantime
      if(mouse_flags & 0x80) {
	spi_uio_cmd_cont(UIO_MOUSE);

	// ----- X axis -------
	if(mouse_pos[X] < -128) {
	  spi8(-128);
	  mouse_pos[X] += 128;
	} else if(mouse_pos[X] > 127) {
	  spi8(127);
	  mouse_pos[X] -= 127;
	} else {
	  spi8(mouse_pos[X]);
	  mouse_pos[X] = 0;
	}

	// ----- Y axis -------
	if(mouse_pos[Y] < -128) {
	  spi8(-128);
	  mouse_pos[Y] += 128;
	} else if(mouse_pos[Y] > 127) {
	  spi8(127);
	  mouse_pos[Y] -= 127;
	} else {
	  spi8(mouse_pos[Y]);
	  mouse_pos[Y] = 0;
	}

	spi8(mouse_flags & 0x03);
	DisableIO();

	// reset flags
	mouse_flags = 0;
      }
    }
  }

  if(core_type == CORE_TYPE_MIST) {
    // do some tos specific monitoring here
    tos_poll();
  }

  if(core_type == CORE_TYPE_8BIT) {
    unsigned char c = 1, f, p=0;

    // check for input data on usart
    USART_Poll();
      
    // check for serial data to be sent

    // check for incoming serial data. this is directly forwarded to the
    // arm rs232 and mixes with debug output.
    spi_uio_cmd_cont(UIO_SIO_IN);
    // status byte is 1000000A with A=1 if data is available
    if((f = spi_in(0)) == 0x81) {
      iprintf("\033[1;36m");
      
      // character 0xff is returned if FPGA isn't configured
      while((f == 0x81) && (c!= 0xff) && (c != 0x00) && (p < 8)) {
	c = spi_in();
	if(c != 0xff && c != 0x00) 
	  iprintf("%c", c);

	f = spi_in();
	p++;
      }
      iprintf("\033[0m");
    }
    DisableIO();

    // sd card emulation
    {
      static char buffer[512];
      static uint32_t buffer_lba = 0xffffffff;
      uint32_t lba;
      uint8_t c = user_io_sd_get_status(&lba);

      // valid sd commands start with "5x" to avoid problems with
      // cores that don't implement this command
      if((c & 0xf0) == 0x50) {

	// debug: If the io controller reports and non-sdhc card, then
	// the core should never set the sdhc flag
	if((c & 3) && !MMC_IsSDHC() && (c & 0x04))
	  iprintf("WARNING: SDHC access to non-sdhc card\n");
 	
	// check if core requests configuration
	if(c & 0x08) {
	  iprintf("core requests SD config\n");
	  user_io_sd_set_config();
	}

	// check if system is trying to access a sdhc card from 
	// a sd/mmc setup

	// check if an SDHC card is inserted
	if(MMC_IsSDHC()) {
	  static char using_sdhc = 1;

	  // SD request and 
	  if((c & 0x03) && !(c & 0x04)) {
	    if(using_sdhc) {
	      // we have not been using sdhc so far? 
	      // -> complain!
	      ErrorMessage(" This core does not support\n"
			   " SDHC cards. Using them may\n"
			   " lead to data corruption.\n\n"
			   " Please use an SD card <2GB!", 0);
	      using_sdhc = 0;
	    }
	  } else
	    // SDHC request from core is always ok
	    using_sdhc = 1;
	}

	if((c & 0x03) == 0x02) {
	  // only write if the inserted card is not sdhc or
	  // if the core uses sdhc
	  if((!MMC_IsSDHC()) || (c & 0x04)) {  
	    uint8_t wr_buf[512];

	    if(user_io_dip_switch1())
	      iprintf("SD WR %d\n", lba);

	    // if we write the sector stored in the read buffer, then
	    // update the read buffer with the new contents
	    if(buffer_lba == lba) 
	      memcpy(buffer, wr_buf, 512);

	      buffer_lba = 0xffffffff;

	    // Fetch sector data from FPGA ...
	    spi_uio_cmd_cont(UIO_SECTOR_WR);
	    spi_block_read(wr_buf);
	    DisableIO();

	    // ... and write it to disk
	    DISKLED_ON;

	    if(sd_image.size) {
	      FileSeek(&sd_image, lba, SEEK_SET);
	      FileWrite(&sd_image, wr_buf);
	    } else
	      MMC_Write(lba, wr_buf);

	    DISKLED_OFF;
	  }
	}

	if((c & 0x03) == 0x01) {

	  if(user_io_dip_switch1())
	    iprintf("SD RD %d\n", lba);
	  
	  // are we using a file as the sd card image?
	  // (C64 floppy does that ...)
	  if(buffer_lba != lba) {
	    DISKLED_ON;
	    if(sd_image.size) {
	      FileSeek(&sd_image, lba, SEEK_SET);
	      FileRead(&sd_image, buffer);
	    } else {
	      // sector read
	      // read sector from sd card if it is not already present in
	      // the buffer
	      MMC_Read(lba, buffer);
	    }
	    buffer_lba = lba;
	    DISKLED_OFF;
	  }

	  if(buffer_lba == lba) {
	    // data is now stored in buffer. send it to fpga
	    spi_uio_cmd_cont(UIO_SECTOR_RD);
	    spi_block_write(buffer);
	    DisableIO();

	    // the end of this transfer acknowledges the FPGA internal
	    // sd card emulation
	  }

	  // just load the next sector now, so it may be prefetched
	  // for the next request already
	  DISKLED_ON;
	  if(sd_image.size) {
	    FileSeek(&sd_image, lba+1, SEEK_SET);
	    FileRead(&sd_image, buffer);
	  } else {
	    // sector read
	    // read sector from sd card if it is not already present in
	    // the buffer
	    MMC_Read(lba+1, buffer);
	  }
	  buffer_lba = lba+1;
	  DISKLED_OFF;
	}
      }
    }

    // frequently check ps2 mouse for events
    if(CheckTimer(mouse_timer)) {
      mouse_timer = GetTimer(MOUSE_FREQ);

      // has ps2 mouse data been updated in the meantime
      if(mouse_flags & 0x08) {
	unsigned char ps2_mouse[3];

	// PS2 format: 
	// YOvfl, XOvfl, dy8, dx8, 1, mbtn, rbtn, lbtn
	// dx[7:0]
	// dy[7:0]
	ps2_mouse[0] = mouse_flags;

	// ------ X axis -----------
	// store sign bit in first byte
	ps2_mouse[0] |= (mouse_pos[X] < 0)?0x10:0x00;
	if(mouse_pos[X] < -255) {
	  // min possible value + overflow flag
	  ps2_mouse[0] |= 0x40;
	  ps2_mouse[1] = -128;
	} else if(mouse_pos[X] > 255) {
	  // max possible value + overflow flag
	  ps2_mouse[0] |= 0x40;
	  ps2_mouse[1] = 255;
	} else 
	  ps2_mouse[1] = mouse_pos[X];

	// ------ Y axis -----------
	// store sign bit in first byte
	ps2_mouse[0] |= (mouse_pos[Y] < 0)?0x20:0x00;
	if(mouse_pos[Y] < -255) {
	  // min possible value + overflow flag
	  ps2_mouse[0] |= 0x80;
	  ps2_mouse[2] = -128;
	} else if(mouse_pos[Y] > 255) {
	  // max possible value + overflow flag
	  ps2_mouse[0] |= 0x80;
	  ps2_mouse[2] = 255;
	} else 
	  ps2_mouse[2] = mouse_pos[Y];
	
	// collect movement info and send at predefined rate
	iprintf("PS2 MOUSE: %x %d %d\n", 
		ps2_mouse[0], ps2_mouse[1], ps2_mouse[2]);

	spi_uio_cmd_cont(UIO_MOUSE);
	spi8(ps2_mouse[0]);
	spi8(ps2_mouse[1]);
	spi8(ps2_mouse[2]);
	DisableIO();

	// reset counters
	mouse_flags = 0;
	mouse_pos[X] = mouse_pos[Y] = 0;
      }
    }

    // --------------- THE FOLLOWING IS DEPRECATED AND WILL BE REMOVED ------------
    // ------------------------ USE SD CARD EMULATION INSTEAD ---------------------

    // raw sector io for the atari800 core which include a full
    // file system driver usually implemented using a second cpu
    static unsigned long bit8_status = 0;
    unsigned long status;

    /* read status byte */
    EnableFpga();
    SPI(UIO_GET_STATUS);
    status = SPI(0);
    status = (status << 8) | SPI(0);
    status = (status << 8) | SPI(0);
    status = (status << 8) | SPI(0);
    DisableFpga();

    if(status != bit8_status) {
      unsigned long sector = (status>>8)&0xffffff;
      char buffer[512];

      bit8_status = status;
      
      // sector read testing 
      DISKLED_ON;

      // sector read
      if(((status & 0xff) == 0xa5) || ((status & 0x3f) == 0x29)) {

	// extended command with 26 bits (for 32GB SDHC)
	if((status & 0x3f) == 0x29) sector = (status>>6)&0x3ffffff;

	bit8_debugf("SECIO rd %ld", sector);

	if(MMC_Read(sector, buffer)) {
	  // data is now stored in buffer. send it to fpga
	  EnableFpga();
	  SPI(UIO_SECTOR_SND);     // send sector data IO->FPGA
	  spi_block_write(buffer);
	  DisableFpga();
	} else
	  bit8_debugf("rd %ld fail", sector);
      }

      // sector write
      if(((status & 0xff) == 0xa6) || ((status & 0x3f) == 0x2a)) {

	// extended command with 26 bits (for 32GB SDHC)
	if((status & 0x3f) == 0x2a) sector = (status>>6)&0x3ffffff;

	bit8_debugf("SECIO wr %ld", sector);

	// read sector from FPGA
	EnableFpga();
	SPI(UIO_SECTOR_RCV);     // receive sector data FPGA->IO
	spi_block_read(buffer);
	DisableFpga();

	if(!MMC_Write(sector, buffer)) 
	  bit8_debugf("wr %ld fail", sector);
      }

      DISKLED_OFF;
    }