Пример #1
0
uint8_t menu_edit_value(uint8_t v, uint8_t min, uint8_t max) {
  uint8_t x = lcd_x;
  uint8_t y = lcd_y;

  lcd_locate(x, y);
  lcd_cursor(true);
  set_busy_led(true);
  for (;;) {
    lcd_printf("%02d", v);
    lcd_locate(x, y);
    for (;;) {
      if (get_key_autorepeat(KEY_PREV)) {
        if (v <= min) v = max;
        else --v;
        break;
      }
      if (get_key_autorepeat(KEY_NEXT)) {
        if (v >= max) v = min;
        else ++v;
        break;
      }
      if (get_key_press(KEY_SEL)) {
        lcd_cursor(false);
        set_busy_led(false);
        return v;
      }
    }
  }
}
Пример #2
0
uint8_t menu_edit_month(uint8_t m) {
  for (;;) {
    lcd_locate(3, 0);
    menu_print_month(m);
    lcd_locate(3, 0);
    set_busy_led(true);
    lcd_cursor(true);
    for (;;) {
      if (get_key_autorepeat(KEY_PREV)) {
        if (m == 0) m = 11;
        else --m;
        break;
      }
      if (get_key_autorepeat(KEY_NEXT)) {
        if (m == 11) m = 0;
        else ++m;
        break;
      }
      if (get_key_press(KEY_SEL)) {
        set_busy_led(false);
        lcd_cursor(false);
        return m;
      }
    }
  }
}
Пример #3
0
static void m2i_rename(path_t *path, cbmdirent_t *dent, uint8_t *newname) {
  uint16_t offset;
  uint8_t *ptr;

  set_busy_led(1);
  /* Locate entry in the M2I file */
  offset = dent->pvt.m2i.offset;
  if (load_entry(path->part, offset)) {
    update_leds();
    return;
  }

  /* Re-load the entry because load_entry modifies it */
  /* Assume this never fails because load_entry was successful */
  image_read(path->part, offset, ops_scratch, M2I_ENTRY_LEN);

  /* Copy the new filename */
  ptr = ops_scratch + M2I_CBMNAME_OFFSET;
  memset(ptr, ' ', CBM_NAME_LENGTH);
  while (*newname)
    *ptr++ = *newname++;

  /* Write new entry */
  image_write(path->part, offset, ops_scratch, M2I_ENTRY_LEN, 1);

  update_leds();
}
Пример #4
0
static void cmd_handler (void)
{
  /* Handle commands and filenames */
  if (ieee_data.ieeeflags & COMMAND_RECVD) {
# ifdef HAVE_HOTPLUG
    /* This seems to be a nice point to handle card changes */
    if (disk_state != DISK_OK) {
      set_busy_led(1);
      /* If the disk was changed the buffer contents are useless */
      if (disk_state == DISK_CHANGED || disk_state == DISK_REMOVED) {
        free_multiple_buffers(FMB_ALL);
        change_init();
        filesystem_init(0);
      } else {
        /* Disk state indicated an error, try to recover by initialising */
        filesystem_init(1);
      }
      update_leds();
    }
# endif
    if (ieee_data.secondary_address == 0x0f) {
      parse_doscommand();                   /* Command channel */
    } else {
      datacrc = 0xffff;                     /* Filename in command buffer */
      file_open(ieee_data.secondary_address);
    }
    command_length = 0;
    ieee_data.ieeeflags &= (uint8_t) ~COMMAND_RECVD;
  } /* COMMAND_RECVD */

  /* We're done, clean up unused buffers */
  free_multiple_buffers(FMB_UNSTICKY);
  d64_bam_commit();
}
Пример #5
0
void menu_adjust_brightness(void) {
  uint8_t i;
  uint8_t min = 0;
  uint8_t max = 255;
  uint8_t res;
  uint8_t step;

  lcd_clear();
  lcd_puts_P(PSTR("Adjust brightness"));
  lcd_locate(0, 1);

  lcd_cursor(false);
  set_busy_led(true);
  for (;;) {
    lcd_locate(0, 1);
    lcd_putc('[');
    for (i = 0; i < 18; i++) {
      lcd_putc(i >= (lcd_brightness / 14) ? ' ' : 0xFF);
    }
    lcd_putc(']');
    res = lcd_set_brightness(lcd_brightness);
    if (res) break;
    for (;;) {
      step = 10;
      if (lcd_brightness < 20 || lcd_brightness > 235) step = 1;
      if (get_key_autorepeat(KEY_PREV)) {
        if (lcd_brightness <= min) lcd_brightness = max;
        else lcd_brightness -= step;
        break;
      }
      if (get_key_autorepeat(KEY_NEXT)) {
        if (lcd_brightness >= max) lcd_brightness = min;
        else lcd_brightness += step;
        break;
      }
      if (get_key_press(KEY_SEL)) {
        lcd_cursor(false);
        set_busy_led(false);
        menu_ask_store_settings();
        return;
      }
    }
  }
  pwm_error();
}
Пример #6
0
/**
 * alloc_buffer - allocates a buffer
 *
 * This function allocates a buffer and marks it as used. It will also
 * turn on the busy LED to notify the user. Returns a pointer to the
 * buffer structure or NULL if no buffer is free.
 */
buffer_t *alloc_buffer(void) {
  buffer_t *buf = alloc_system_buffer();
  if (buf != NULL) {
    buf->secondary = 0;
    active_buffers++;
    set_busy_led(1);
  }
  return buf;
}
Пример #7
0
void menu_adjust_contrast(void) {
  uint8_t i;
  uint8_t min = 0;
  uint8_t max = LCD_COLS - 2;
  uint8_t res;

  lcd_clear();
  lcd_puts_P(PSTR("Adjust LCD contrast"));
  lcd_locate(0, 1);

  lcd_cursor(false);
  set_busy_led(true);
  for (;;) {
    lcd_locate(0, 1);
    lcd_putc('[');
    for (i = 0; i < LCD_COLS - 2; i++) {
      lcd_putc(i >= lcd_contrast ? ' ' : 0xFF);
    }
    lcd_putc(']');
    res = lcd_set_contrast(lcd_contrast);
    if (res) break;
    for (;;) {
      if (get_key_autorepeat(KEY_PREV)) {
        if (lcd_contrast <= min) lcd_contrast = max;
        else --lcd_contrast;
        break;
      }
      if (get_key_autorepeat(KEY_NEXT)) {
        if (lcd_contrast >= max) lcd_contrast = min;
        else ++lcd_contrast;
        break;
      }
      if (get_key_press(KEY_SEL)) {
        lcd_cursor(false);
        set_busy_led(false);
        menu_ask_store_settings();
        return;
      }
    }
  }
  pwm_error();
}
Пример #8
0
static void confirm_blink(uint8_t type) {
  uint8_t i;

  for (i=0;i<2;i++) {
    tick_t targettime;

#ifdef SINGLE_LED
    set_dirty_led(1);
#else
    if (!i || type & 1)
      set_dirty_led(1);
    if (!i || type & 2)
      set_busy_led(1);
#endif
    targettime = ticks + MS_TO_TICKS(100);
    while (time_before(ticks,targettime)) ;

    set_dirty_led(0);
    set_busy_led(0);
    targettime = ticks + MS_TO_TICKS(100);
    while (time_before(ticks,targettime)) ;
  }
}
Пример #9
0
/**
 * alloc_linked_buffers - allocates linked buffers
 * @count    : Number of buffers to allocate
 *
 * This function allocates count buffers, marks them as used and
 * links them. It will also turn on the busy LED to notify the user.
 * Returns a pointer to the first buffer structure or NULL if
 * not enough buffers are free. The data segments of the allocated
 * buffers are guaranteed to be continuous.
 */
buffer_t *alloc_linked_buffers(uint8_t count) {
  uint8_t i,freebufs,start;

  freebufs = 0;
  start    = 0;
  for (i=0;i<CONFIG_BUFFER_COUNT;i++) {
    if (buffers[i].allocated) {
      /* Look for continuous buffers */
      /* Switching data segments is possible, but probably not required */
      freebufs = 0;
    } else {
      if (freebufs == 0)
        start = i;
      freebufs++;
      /* Found enough free space */
      if (freebufs == count)
        break;
    }
  }

  if (freebufs < count) {
    set_error(ERROR_NO_CHANNEL);
    return NULL;
  }

  /* Chain the buffers */
  for (i=0;i<count;i++) {
    alloc_specific_buffer(start+i);
    active_buffers++;
    buffers[start+i].secondary = 0;
    buffers[start+i].pvt.buffer.next  = &buffers[start+i+1];
    buffers[start+i].pvt.buffer.first = &buffers[start];
    buffers[start+i].pvt.buffer.size  = count;
  }

  set_busy_led(1);

  buffers[start+count-1].pvt.buffer.next = NULL;

  return &buffers[start];
}
Пример #10
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
  }
}
Пример #11
0
static inline __attribute__((always_inline)) void update_leds(void) {
  set_busy_led(active_buffers != 0);
}
Пример #12
0
/**
 * create_changelist - create a swap list in a directory
 * @path    : path where the swap list should be created
 * @filename: name of the swap list file
 *
 * This function creates a swap list in @path by scanning that
 * directory and writing the names of all disk images it finds
 * into @filename. Returns nonzero if at least one image was found.
 */
static uint8_t create_changelist(path_t *path, uint8_t *filename) {
  FRESULT res;
  FILINFO finfo;
  DIR dh;
  FIL fh;
  UINT byteswritten;
  uint8_t *name;
  uint8_t found = 0;

  /* open directory */
  res = l_opendir(&partition[path->part].fatfs, path->dir.fat, &dh);
  if (res != FR_OK)
    return 0;

  /* open file */
  res = f_open(&partition[path->part].fatfs, &fh, filename, FA_WRITE | FA_CREATE_ALWAYS);
  if (res != FR_OK)
    return 0;

  /* scan directory */
  set_busy_led(1);
  finfo.lfn = ops_scratch;

  while (1) {
    res = f_readdir(&dh, &finfo);
    if (res != FR_OK)
      break;

    if (finfo.fname[0] == 0)
      break;

    if (!(finfo.fattrib & AM_DIR)) {
      if (check_imageext(finfo.fname) == IMG_IS_DISK) {
        /* write the name of disk image to file */
        found = 1;

        if (ops_scratch[0] != 0)
          name = ops_scratch;
        else
          name = finfo.fname;

        res = f_write(&fh, name, ustrlen(name), &byteswritten);
        if (res != FR_OK || byteswritten == 0)
          break;

        /* add line terminator */
        finfo.fname[0] = 0x0d;
        finfo.fname[1] = 0x0a;
        res = f_write(&fh, finfo.fname, 2, &byteswritten);
        if (res != FR_OK || byteswritten == 0)
          break;
      }
    }
  }

  f_close(&fh);

  set_busy_led(0);

  return found;
}
Пример #13
0
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;
}
Пример #14
0
/**
 * update_leds - set LEDs to correspond to the buffer status
 *
 * This function sets the busy/dirty LEDs to correspond to the current state
 * of the buffers, i.e. busy on of at least one non-system buffer is
 * allocated and dirty on if at least one buffer is dirty.
 * Call if you have manually changed the LEDs and you want to restore the
 * "default" state.
 */
void update_leds(void) {
  set_busy_led(active_buffers != 0);
  set_dirty_led(get_dirty_buffer_count() != 0);
}
Пример #15
0
bool menu(void) {
  uint8_t mp = 0;
  uint8_t my = 0;
  uint8_t i;
  uint8_t old_bus;
  bool action;

  old_bus = active_bus;
  bus_sleep(true);

  menu_select_status(); // disable splash screen if still active
  set_error(ERROR_OK);
  for (;;) {
    set_busy_led(false); set_dirty_led(true);
    lcd_clear();
    for (i = 0; i < LCD_LINES; i++) {
      lcd_locate(0, i);
      rom_menu_main(mp - my + i);
    }

    lcd_cursor(true);
    for (;;) {
      action = false;
      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) {
          // Move up
          --mp;
          if (my > 0) {
            --my;               // Move within same page
          } else {
            mp = LCD_LINES - 1;
            my = LCD_LINES - 1; // page up
            break;
          }
        } else {
          // flip down to last menu entry
          my = MAIN_MENU_LAST_ENTRY % LCD_LINES;
          mp = MAIN_MENU_LAST_ENTRY;
          break;
        }
      }
      if (get_key_autorepeat(KEY_NEXT)) {
        if (mp < MAIN_MENU_LAST_ENTRY) {
          ++mp;
          if (my < (LCD_LINES - 1)) {
            ++my;               // Move within same page
          } else {
            my = 0;             // page down
            break;
          }
        } else {
          // flip up to first menu entry
          mp = 0;
          my = 0;
          break;
        }
      }
      if (get_key_press(KEY_SEL)) {
        action = true;
        break;
      }
    }
    lcd_cursor(false);
    if (!action) continue;
    lcd_clear();
    if      (mp == 1) menu_browse_files();
    else if (mp == 2) menu_device_number();
    else if (mp == 3) menu_set_clock();
    else if (mp == 4) menu_select_bus();
    else if (mp == 5) menu_adjust_contrast();
    else if (mp == 6) menu_adjust_brightness();
    else  break;
    if (current_error != ERROR_OK) break;
  }

  bus_sleep(false);
  lcd_draw_screen(SCRN_STATUS);
  update_leds();
  return old_bus != active_bus;
}
Пример #16
0
void ieee_mainloop(void) {
  int16_t cmd = 0;

  set_error(ERROR_DOSVERSION);

  ieee_data.bus_state = BUS_IDLE;
  ieee_data.device_state = DEVICE_IDLE;
  for(;;) {
    switch(ieee_data.bus_state) {
      case BUS_SLEEP:                               /* BUS_SLEEP */
        set_atn_irq(0);
        ieee_bus_idle();
        set_error(ERROR_OK);
        set_busy_led(0);
        uart_puts_P(PSTR("ieee.c/sleep ")); set_dirty_led(1);

        /* Wait until the sleep key is used again */
        while (!key_pressed(KEY_SLEEP))
          system_sleep();
        reset_key(KEY_SLEEP);

        set_atn_irq(1);
        update_leds();

        ieee_data.bus_state = BUS_IDLE;
        break;

      case BUS_IDLE:                                /* BUS_IDLE */
        ieee_bus_idle();
        while(IEEE_ATN) {   ;               /* wait for ATN */
          if (key_pressed(KEY_NEXT | KEY_PREV | KEY_HOME)) {
            change_disk();
          } else if (key_pressed(KEY_SLEEP)) {
            reset_key(KEY_SLEEP);
            ieee_data.bus_state = BUS_SLEEP;
            break;
          } else if (display_found && key_pressed(KEY_DISPLAY)) {
            display_service();
            reset_key(KEY_DISPLAY);
          }
          system_sleep();
      }

      if (ieee_data.bus_state != BUS_SLEEP)
        ieee_data.bus_state = BUS_FOUNDATN;
      break;

      case BUS_FOUNDATN:                            /* BUS_FOUNDATN */
        ieee_data.bus_state = BUS_ATNPROCESS;
        cmd = ieee_getc();
      break;

      case BUS_ATNPROCESS:                          /* BUS_ATNPROCESS */
        if(cmd < 0) {
          uart_putc('c');
          ieee_data.bus_state = BUS_IDLE;
          break;
        } else cmd &= 0xFF;
        uart_puts_p("ATN "); uart_puthex(cmd);
        uart_putcrlf();

        if (cmd == 0x3f) {                                  /* UNLISTEN */
          if(ieee_data.device_state == DEVICE_LISTEN) {
            ieee_data.device_state = DEVICE_IDLE;
            uart_puts_p("UNLISTEN\r\n");
          }
          ieee_data.bus_state = BUS_IDLE;
          break;
        } else if (cmd == 0x5f) {                           /* UNTALK */
          if(ieee_data.device_state == DEVICE_TALK) {
            ieee_data.device_state = DEVICE_IDLE;
            uart_puts_p("UNTALK\r\n");
          }
          ieee_data.bus_state = BUS_IDLE;
          break;
        } else if (cmd == (0x40 + device_address)) {        /* TALK */
          uart_puts_p("TALK ");
          uart_puthex(device_address); uart_putcrlf();
          ieee_data.device_state = DEVICE_TALK;
          /* disk drives never talk immediatly after TALK, so stay idle
             and wait for a secondary address given by 0x60-0x6f DATA */
          ieee_data.bus_state = BUS_IDLE;
          break;
        } else if (cmd == (0x20 + device_address)) {        /* LISTEN */
          ieee_data.device_state = DEVICE_LISTEN;
          uart_puts_p("LISTEN ");
          uart_puthex(device_address); uart_putcrlf();
          ieee_data.bus_state = BUS_IDLE;
          break;
        } else if ((cmd & 0xf0) == 0x60) {                  /* DATA */
          /* 8250LP sends data while ATN is still active, so wait
             for bus controller to release ATN or we will misinterpret
             data as a command */
          while(!IEEE_ATN);
          if(ieee_data.device_state == DEVICE_LISTEN) {
            cmd = ieee_listen_handler(cmd);
            cmd_handler();
            break;
          } else if (ieee_data.device_state == DEVICE_TALK) {
            ieee_data.secondary_address = cmd & 0x0f;
            uart_puts_p("DATA T ");
            uart_puthex(ieee_data.secondary_address);
            uart_putcrlf();
            if(ieee_talk_handler() == TIMEOUT_ABORT) {
              ieee_data.device_state = DEVICE_IDLE;
            }
            ieee_data.bus_state = BUS_IDLE;
            break;
          } else {
            ieee_data.bus_state = BUS_IDLE;
            break;
          }
        } else if (ieee_data.device_state == DEVICE_IDLE) {
          ieee_data.bus_state = BUS_IDLE;
          break;
          /* ----- if we reach this, we're LISTENer or TALKer ----- */
        } else if ((cmd & 0xf0) == 0xe0) {                  /* CLOSE */
          ieee_data.secondary_address = cmd & 0x0f;
          uart_puts_p("CLOSE ");
          uart_puthex(ieee_data.secondary_address);
          uart_putcrlf();
          /* Close all buffers if sec. 15 is closed */
          if(ieee_data.secondary_address == 15) {
            free_multiple_buffers(FMB_USER_CLEAN);
          } else {
            /* Close a single buffer */
            buffer_t *buf;
            buf = find_buffer (ieee_data.secondary_address);
            if (buf != NULL) {
              buf->cleanup(buf);
              free_buffer(buf);
            }
          }
          ieee_data.bus_state = BUS_IDLE;
          break;
        } else if ((cmd & 0xf0) == 0xf0) {                  /* OPEN */
          cmd = ieee_listen_handler(cmd);
          cmd_handler();
          break;
        } else {
          /* Command for other device or unknown command */
          ieee_data.bus_state = BUS_IDLE;
        }
      break;
    }   /* switch   */
  }     /* for()    */
}
Пример #17
0
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);
}