void change_disk(void) { path_t path; if (swaplist.fs == NULL) { /* No swaplist active, try using AUTOSWAP.LST */ /* change_disk is called from the IEC idle loop, so ops_scratch is free */ ustrcpy_P(ops_scratch, autoswap_lst_name); path.dir = partition[current_part].current_dir; path.part = current_part; if (key_pressed(KEY_PREV)) set_changelist_internal(&path, ops_scratch, 1); else set_changelist_internal(&path, ops_scratch, 0); if (swaplist.fs == NULL) { /* No swap list found, create one if key was "home" */ if (key_pressed(KEY_HOME)) { uint8_t swapname[16]; // FIXME: magic constant ustrcpy_P(swapname, autoswap_gen_name); if (create_changelist(&path, swapname)) { set_changelist_internal(&path, swapname, 0); globalflags |= AUTOSWAP_ACTIVE; } } /* reset error and exit */ set_error(ERROR_OK); reset_key(0xff); // <- lazy return; } else { /* Autoswaplist found, mark it as active */ /* and exit because the first image is already mounted. */ globalflags |= AUTOSWAP_ACTIVE; reset_key(0xff); // <- lazy return; } } /* Mount the next image in the list */ if (key_pressed(KEY_NEXT)) { linenum++; reset_key(KEY_NEXT); if (mount_line()) confirm_blink(BLINK_FORWARD); } else if (key_pressed(KEY_PREV)) { linenum--; reset_key(KEY_PREV); if (mount_line()) confirm_blink(BLINK_BACKWARD); } else if (key_pressed(KEY_HOME)) { linenum = 0; reset_key(KEY_HOME); if (mount_line()) confirm_blink(BLINK_HOME); } }
static void menu_chdir(void) { cbmdirent_t dent; dh_t dh; path_t path; int8_t res; menustate = MENU_CHDIR; display_menu_reset(); ustrcpy_P(displaybuffer,PSTR("\xc3""ANCEL")); display_menu_add(displaybuffer); displaybuffer[0] = '_'; displaybuffer[1] = 0; display_menu_add(displaybuffer); path.part = current_part; path.dir = partition[current_part].current_dir; if (opendir(&dh, &path)) { menustate = MENU_NONE; return; } while (1) { res = readdir(&dh, &dent); if (res > 0) return; if (res < 0) break; /* Skip hidden files and only add image files on FAT */ if (!(dent.typeflags & FLAG_HIDDEN)) { if ((dent.typeflags & TYPE_MASK) == TYPE_DIR) { display_menu_add(dent.name); } else if (dent.opstype == OPSTYPE_FAT && check_imageext(dent.pvt.fat.realname) != IMG_UNKNOWN) { display_menu_add(dent.name); } } } display_menu_show(0); }
int main(void) { /* Early system initialisation */ early_board_init(); system_init_early(); leds_init(); set_busy_led(1); set_dirty_led(0); /* Due to an erratum in the LPC17xx chips anything that may change */ /* peripheral clock scalers must come before system_init_late() */ uart_init(); #ifndef SPI_LATE_INIT spi_init(SPI_SPEED_SLOW); #endif timer_init(); i2c_init(); /* Second part of system initialisation, switches to full speed on ARM */ system_init_late(); enable_interrupts(); /* Prompt software name and version string */ uart_puts_P(PSTR("\r\nNODISKEMU " VERSION "\r\n")); /* Internal-only initialisation, called here because it's faster */ buffers_init(); buttons_init(); /* Anything that does something which needs the system clock */ /* should be placed after system_init_late() */ rtc_init(); // accesses I2C disk_init(); // accesses card read_configuration(); // restores configuration, may change device address filesystem_init(0); // FIXME: change_init(); #ifdef CONFIG_REMOTE_DISPLAY /* at this point all buffers should be free, */ /* so just use the data area of the first to build the string */ uint8_t *strbuf = buffers[0].data; ustrcpy_P(strbuf, versionstr); ustrcpy_P(strbuf+ustrlen(strbuf), longverstr); if (display_init(ustrlen(strbuf), strbuf)) { display_address(device_address); display_current_part(0); } #endif set_busy_led(0); #if defined(HAVE_SD) /* card switch diagnostic aid - hold down PREV button to use */ if (menu_system_enabled && get_key_press(KEY_PREV)) board_diagnose(); #endif if (menu_system_enabled) lcd_splashscreen(); bus_interface_init(); bus_init(); read_configuration(); late_board_init(); for (;;) { if (menu_system_enabled) lcd_refresh(); else { lcd_clear(); lcd_printf("#%d", device_address); } /* Unit number may depend on hardware and stored settings */ /* so present it here at last */ printf("#%02d\r\n", device_address); bus_mainloop(); bus_interface_init(); bus_init(); // needs delay, inits device address with HW settings } }
void display_service(void) { if (menustate == MENU_NONE) { /* No menu active, upload+run system menu */ uint8_t i; /* Dummy read to reset the interrupt line */ i2c_read_register(DISPLAY_I2C_ADDR, DISPLAY_MENU_GETSELECTION); display_menu_reset(); i = 0; while (pgm_read_byte(systemmenu+i)) { ustrcpy_P(displaybuffer, systemmenu+i); display_menu_add(displaybuffer); i += ustrlen(displaybuffer)+1; } display_menu_show(0); menustate = MENU_SYSTEM; } else if (menustate == MENU_SYSTEM) { /* Selection on the system menu */ uint8_t sel = i2c_read_register(DISPLAY_I2C_ADDR, DISPLAY_MENU_GETSELECTION); switch (sel) { case SYSMENU_CHDIR: menu_chdir(); break; case SYSMENU_CHADDR: menu_chaddr(); break; case SYSMENU_STORE: menustate = MENU_NONE; write_configuration(); break; case SYSMENU_CANCEL: menustate = MENU_NONE; return; } } else if (menustate == MENU_CHADDR) { /* New address selected */ uint8_t sel = i2c_read_register(DISPLAY_I2C_ADDR, DISPLAY_MENU_GETSELECTION); device_address = sel+4; menustate = MENU_NONE; display_address(device_address); } else if (menustate == MENU_CHDIR) { /* New directory selected */ uint8_t sel = i2c_read_register(DISPLAY_I2C_ADDR, DISPLAY_MENU_GETSELECTION); path_t path; cbmdirent_t dent; menustate = MENU_NONE; if (sel == 0) /* Cancel */ return; /* Read directory name into displaybuffer */ path.part = current_part; path.dir = partition[current_part].current_dir; if (sel == 1) { /* Previous directory */ dent.name[0] = '_'; dent.name[1] = 0; } else { i2c_read_registers(DISPLAY_I2C_ADDR, DISPLAY_MENU_GETENTRY, sizeof(displaybuffer), displaybuffer); if (first_match(&path, displaybuffer, FLAG_HIDDEN, &dent)) return; } chdir(&path, &dent); update_current_dir(&path); } }
void menu_browse_files(void) { buffer_t *buf; buffer_t *buf_tbl; buffer_t *buf_cur; buffer_t *first_buf; path_t path; cbmdirent_t dent; uint16_t entries; uint8_t entry_num; bool fat_filesystem; uint8_t i; uint8_t my; uint16_t mp; bool action; uint16_t stack_mp[MAX_LASTPOS]; uint8_t stack_my[MAX_LASTPOS]; uint8_t pos_stack; uint8_t save_active_buffers; pos_stack = 0; memset(stack_mp, 0, sizeof(stack_mp)); memset(stack_my, 0, sizeof(stack_my)); save_active_buffers = active_buffers; start: lcd_clear(); lcd_puts_P(PSTR("Reading...")); buf = buf_tbl = buf_cur = first_buf = NULL; entries = entry_num = mp = 0; fat_filesystem = false; // Allocate one buffer, used to read a single directory entry if ((buf = alloc_system_buffer()) == NULL) return; // Allocate buffers with continuous data segments // Stores pointers to directory entries for qsort if ((buf_tbl = alloc_linked_buffers(CONFIG_DIR_BUFFERS)) == NULL) return; // Buffers to store the actual diretory entries. // Whilst the directory grows, new buffers get allocated and linked if ((buf_cur = alloc_system_buffer()) == NULL) return; first_buf = buf_cur; // Allocating buffers affects the LEDs set_busy_led(false); set_dirty_led(true); path.part = current_part; path.dir = partition[path.part].current_dir; uart_trace(&path.dir, 0, sizeof(dir_t)); uart_putcrlf(); uart_flush(); if (opendir(&buf->pvt.dir.dh, &path)) return; for (;;) { if (next_match(&buf->pvt.dir.dh, buf->pvt.dir.matchstr, buf->pvt.dir.match_start, buf->pvt.dir.match_end, buf->pvt.dir.filetype, &dent) == 0) { uint8_t e_flags = 0; if (dent.opstype == OPSTYPE_FAT) { fat_filesystem = true; if (check_imageext(dent.pvt.fat.realname) != IMG_UNKNOWN) e_flags |= E_IMAGE; } // Current block full? if (entry_num == ENTRIES_PER_BLOCK) { entry_num = 0; buffer_t *old_buf = buf_cur; if ((buf_cur = alloc_system_buffer()) == NULL) { printf("alloc buf_cur failed, %d entries", entries); goto cleanup; } set_busy_led(false); set_dirty_led(true); buf_cur->pvt.buffer.next = NULL; old_buf->pvt.buffer.next = buf_cur; } // Store entry ep[entries] = (entry_t *) (buf_cur->data + entry_num * sizeof(entry_t)); ustrncpy(ep[entries]->filename, dent.name, 16); ep[entries]->filesize = dent.blocksize; if ((dent.typeflags & EXT_TYPE_MASK) == TYPE_DIR) e_flags |= E_DIR; ep[entries]->flags = e_flags; entries++; entry_num++; } else { // No more directory entries to read break; } } printf("%d entries\r\n", entries); if (fat_filesystem) qsort(ep, entries, sizeof(entry_t*), compare); for (uint16_t i = 0; i < entries; i++) { printf("%3u: ", i); if (ep[i]->flags & E_DIR) uart_puts_P(PSTR(" DIR ")); else if (ep[i]->flags & E_IMAGE) uart_puts_P(PSTR(" IMG ")); else printf("%4u ", ep[i]->filesize); uint8_t filename[16 + 1]; ustrncpy(filename, ep[i]->filename, 16); filename[16] = '\0'; pet2asc(filename); printf("%s\r\n", filename); uart_flush(); } uart_putcrlf(); #define DIRNAV_OFFSET 2 #define NAV_ABORT 0 #define NAV_PARENT 1 mp = stack_mp[pos_stack]; my = stack_my[pos_stack]; printf("mp set to %d\r\n", mp); if (mp < (LCD_LINES - 1)) my = mp; else my = 0; action = false; for (i=0; i < MAX_LASTPOS; i++) { if (pos_stack == i) uart_putc('>'); printf("%d ", stack_mp[i]); } uart_putcrlf(); for (;;) { lcd_clear(); for (i = 0; i < LCD_LINES; i++) { lcd_locate(0, i); int8_t y = mp - my + i; if (y < 0) return; // should not happen! if (y < DIRNAV_OFFSET) { rom_menu_browse(y); } else { y -= DIRNAV_OFFSET; if (y >= entries) { lcd_puts_P(PSTR("-- End of dir --")); break; } else { lcd_print_dir_entry(y); } } } lcd_cursor(true); for (;;) { lcd_locate(0, my); //printf("mp: %u my: %u\r\n", mp, my); //while (!get_key_state(KEY_ANY)); if (get_key_autorepeat(KEY_PREV)) { if (mp > 0) { --mp; if (my > 0) --my; else { my = LCD_LINES - 1; if (mp < LCD_LINES) { while ((mp - my) >= DIRNAV_OFFSET) { --my; // TODO: is this really necessary? uart_puts_P(PSTR("my fixed\r\n")); } } break; } } else { my = LCD_LINES - 2; mp = entries + DIRNAV_OFFSET - 1; break; } } if (get_key_autorepeat(KEY_NEXT)) { if (mp < (entries -1 + DIRNAV_OFFSET)) { ++mp; if (my < (LCD_LINES - 1)) ++my; else { my = 0; break; } } else { mp = 0; my = 0; break; } } if (get_key_press(KEY_SEL)) { action = true; break; } } lcd_cursor(false); if (!action) continue; if (mp == NAV_ABORT) goto cleanup; if (mp == NAV_PARENT) { uart_puts_P(PSTR("CD_\r\n")); ustrcpy_P(command_buffer, PSTR("CD_")); command_length = 3; parse_doscommand(); clear_command_buffer(); stack_mp[pos_stack] = 0; stack_my[pos_stack] = 0; if (pos_stack > 0) --pos_stack; printf("pos_stack set to %d\r\n", pos_stack); if (current_error != ERROR_OK) goto cleanup; goto reread; } if (ep[mp - DIRNAV_OFFSET]->flags & E_DIR || ep[mp - DIRNAV_OFFSET]->flags & E_IMAGE) { clear_command_buffer(); ustrcpy_P(command_buffer, PSTR("CD:")); ustrncpy(command_buffer + 3, ep[mp - DIRNAV_OFFSET]->filename, 16); command_length = ustrlen(command_buffer); parse_doscommand(); clear_command_buffer(); if (current_error != ERROR_OK) goto cleanup; if (pos_stack < MAX_LASTPOS) { stack_mp[pos_stack] = mp; stack_my[pos_stack++] = my; printf("pos_stack set to %d\r\n", pos_stack); } goto reread; } } reread: free_buffer(buf); buffer_t *p = buf_tbl; do { p->allocated = 0; p = p->pvt.buffer.next; } while (p != NULL); p = first_buf; if (p != NULL) do { p->allocated = 0; p = p->pvt.buffer.next; } while (p != NULL); set_busy_led(false); set_dirty_led(true); active_buffers = save_active_buffers; if (mp == NAV_ABORT) return; goto start; cleanup: mp = NAV_ABORT; goto reread; }
int main(void) { /* Early system initialisation */ board_init(); system_init_early(); leds_init(); set_busy_led(1); set_dirty_led(0); /* Due to an erratum in the LPC17xx chips anything that may change */ /* peripheral clock scalers must come before system_init_late() */ uart_init(); #ifndef SPI_LATE_INIT spi_init(SPI_SPEED_SLOW); #endif timer_init(); bus_interface_init(); i2c_init(); /* Second part of system initialisation, switches to full speed on ARM */ system_init_late(); enable_interrupts(); /* Internal-only initialisation, called here because it's faster */ buffers_init(); buttons_init(); /* Anything that does something which needs the system clock */ /* should be placed after system_init_late() */ bus_init(); // needs delay rtc_init(); // accesses I2C disk_init(); // accesses card read_configuration(); fatops_init(0); change_init(); uart_puts_P(PSTR("\r\nsd2iec " VERSION " #")); uart_puthex(device_address); uart_putcrlf(); #ifdef CONFIG_REMOTE_DISPLAY /* at this point all buffers should be free, */ /* so just use the data area of the first to build the string */ uint8_t *strbuf = buffers[0].data; ustrcpy_P(strbuf, versionstr); ustrcpy_P(strbuf+ustrlen(strbuf), longverstr); if (display_init(ustrlen(strbuf), strbuf)) { display_address(device_address); display_current_part(0); } #endif set_busy_led(0); #if defined(HAVE_SD) && BUTTON_PREV != 0 /* card switch diagnostic aid - hold down PREV button to use */ if (!(buttons_read() & BUTTON_PREV)) { while (buttons_read() & BUTTON_NEXT) { set_dirty_led(sdcard_detect()); # ifndef SINGLE_LED set_busy_led(sdcard_wp()); # endif } reset_key(0xff); } #endif bus_mainloop(); while (1); }