static void cdc_puts(char *str) { unsigned char i=0; while(*str) { if(*str == '\n') cdc_control_tx('\r'); cdc_control_tx(*str++); } cdc_control_tx('\r'); cdc_control_tx('\n'); cdc_control_flush(); }
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; }