Ejemplo n.º 1
0
/*
 * Data i/o: send byte to device.
 * Return received byte.
 */
unsigned dev_sdcard_io (cpu_mips_t *cpu, unsigned data)
{
    pic32_t *pic32 = (pic32_t*) cpu->vm->hw_data;
    sdcard_t *d = pic32->sdcard[0].select ? &pic32->sdcard[0] :
                  pic32->sdcard[1].select ? &pic32->sdcard[1] : 0;
    unsigned reply;

    if (! d || ! d->fd) {
        TRACE ("sdcard: unselected i/o\n");
        return 0xFF;
    }
    data = (unsigned char) data;
    reply = 0xFF;
    if (d->count == 0) {
        d->buf[0] = data;
        if (data != 0xFF)
            d->count++;
    } else {
        switch (d->buf[0]) {
        case CMD_GO_IDLE:               /* CMD0: reset */
            if (d->count >= 7)
                break;
            d->buf [d->count++] = data;
            if (d->count == 7)
                reply = 0x01;
            break;
        case CMD_APP:                   /* CMD55: application prefix */
            if (d->count >= 7)
                break;
            d->buf [d->count++] = data;
            if (d->count == 7) {
                reply = 0;
                d->count = 0;
            }
            break;
        case CMD_SEND_OP_SDC:           /* ACMD41: initialization */
            if (d->count >= 7)
                break;
            d->buf [d->count++] = data;
            if (d->count == 7)
                reply = 0;
            break;
        case CMD_SET_BLEN:              /* Set block length */
            if (d->count >= 7)
                break;
            d->buf [d->count++] = data;
            if (d->count == 7) {
                d->blen = d->buf[1] << 24 | d->buf[2] << 16 |
                    d->buf[3] << 8 | d->buf[4];
                TRACE ("sdcard%d: set block length %u bytes\n", d->unit, d->blen);
                reply = (d->blen > 0 && d->blen <= 1024) ? 0 : 4;
            }
            break;
        case CMD_SET_WBECNT:            /* Set write block erase count */
            if (d->count >= 7)
                break;
            d->buf [d->count++] = data;
            if (d->count == 7) {
                d->wbecnt = d->buf[1] << 24 | d->buf[2] << 16 |
                    d->buf[3] << 8 | d->buf[4];
                TRACE ("sdcard%d: set write block erase count %u\n", d->unit, d->wbecnt);
                reply = 0;
                d->count = 0;
            }
            break;
        case CMD_SEND_CSD:              /* Get card data */
            if (d->count >= 7)
                break;
            d->buf [d->count++] = data;
            if (d->count == 7) {
                /* Send reply */
                TRACE ("sdcard%d: send media size %u sectors\n",
                    d->unit, d->kbytes * 2);
                reply = 0;
                d->limit = 16 + 3;
                d->count = 1;
                d->buf[0] = 0;
                d->buf[1] = DATA_START_BLOCK;
                d->buf[2+0] = 1 << 6;     /* SDC ver 2.00 */
                d->buf[2+1] = 0;
                d->buf[2+2] = 0;
                d->buf[2+3] = 0;
                d->buf[2+4] = 0;
                d->buf[2+5] = 0;
                d->buf[2+6] = 0;
                d->buf[2+7] = 0;
                d->buf[2+8] = (d->kbytes / 512 - 1) >> 8;
                d->buf[2+9] = d->kbytes / 512 - 1;
                d->buf[2+10] = 0;
                d->buf[2+11] = 0;
                d->buf[2+12] = 0;
                d->buf[2+13] = 0;
                d->buf[2+14] = 0;
                d->buf[2+15] = 0;
                d->buf[d->limit - 1] = 0xFF;
                d->buf[d->limit] = 0xFF;
            }
            break;
        case CMD_READ_SINGLE:           /* Read block */
            if (d->count >= 7)
                break;
            d->buf [d->count++] = data;
            if (d->count == 7) {
                /* Send reply */
                reply = 0;
                d->offset = d->buf[1] << 24 | d->buf[2] << 16 |
                    d->buf[3] << 8 | d->buf[4];
                TRACE ("sdcard%d: read offset %#x, length %u kbytes\n",
                    d->unit, d->offset, d->blen);
                d->limit = d->blen + 3;
                d->count = 1;
                d->buf[0] = 0;
                d->buf[1] = DATA_START_BLOCK;
                sdcard_read_data (d->fd, d->offset, &d->buf[2], d->blen);
                d->buf[d->limit - 1] = 0xFF;
                d->buf[d->limit] = 0xFF;
            }
            break;
        case CMD_READ_MULTIPLE:         /* Read multiple blocks */
            if (d->count >= 7)
                break;
            d->buf [d->count++] = data;
            if (d->count == 7) {
                /* Send reply */
                reply = 0;
                d->read_multiple = 1;
                d->offset = d->buf[1] << 24 | d->buf[2] << 16 |
                    d->buf[3] << 8 | d->buf[4];
                TRACE ("sdcard%d: read offset %#x, length %u kbytes\n",
                    d->unit, d->offset, d->blen);
                d->limit = d->blen + 3;
                d->count = 1;
                d->buf[0] = 0;
                d->buf[1] = DATA_START_BLOCK;
                sdcard_read_data (d->fd, d->offset, &d->buf[2], d->blen);
                d->buf[d->limit - 1] = 0xFF;
                d->buf[d->limit] = 0xFF;
            }
            break;
        case CMD_WRITE_SINGLE:          /* Write block */
            if (d->count >= sizeof (d->buf))
                break;
            d->buf [d->count++] = data;
            if (d->count == 7) {
                /* Accept command */
                reply = 0;
                d->offset = d->buf[1] << 24 | d->buf[2] << 16 |
                    d->buf[3] << 8 | d->buf[4];
                TRACE ("sdcard%d: write offset %#x\n", d->unit, d->offset);
            } else if (d->count == 7 + d->blen + 2 + 2) {
                if (d->buf[7] == DATA_START_BLOCK) {
                    /* Accept data */
                    reply = 0x05;
                    d->offset = d->buf[1] << 24 | d->buf[2] << 16 |
                        d->buf[3] << 8 | d->buf[4];
                    sdcard_write_data (d->fd, d->offset, &d->buf[8], d->blen);
                    TRACE ("sdcard%d: write data, length %u kbytes\n", d->unit, d->blen);
                } else {
                    /* Reject data */
                    reply = 4;
                    TRACE ("sdcard%d: reject write data, tag=%02x\n", d->unit, d->buf[7]);
                }
            }
            break;
        case CMD_WRITE_MULTIPLE:        /* Write multiple blocks */
            if (d->count >= 7)
                break;
            d->buf [d->count++] = data;
            if (d->count == 7) {
                /* Accept command */
                reply = 0;
                d->offset = d->buf[1] << 24 | d->buf[2] << 16 |
                    d->buf[3] << 8 | d->buf[4];
                TRACE ("sdcard%d: write multiple offset %#x\n", d->unit, d->offset);
                d->count = 0;
            }
            break;
        case WRITE_MULTIPLE_TOKEN:      /* Data for write-miltiple */
            if (d->count >= sizeof (d->buf))
                break;
            d->buf [d->count++] = data;
            if (d->count == 2 + d->blen + 2) {
                /* Accept data */
                reply = 0x05;
                sdcard_write_data (d->fd, d->offset, &d->buf[1], d->blen);
                TRACE ("sdcard%d: write sector %u, length %u kbytes\n",
                    d->unit, d->offset / 512, d->blen);
                d->offset += 512;
                d->count = 0;
            }
            break;
        case CMD_STOP:                  /* Stop read-multiple sequence */
            if (d->count > 1)
                break;
            d->read_multiple = 0;
            reply = 0;
            break;
        case 0:                         /* Reply */
            if (d->count <= d->limit) {
                reply = d->buf [d->count++];
                break;
            }
            if (d->read_multiple) {
                /* Next read-multiple block. */
                d->offset += d->blen;
                d->count = 1;
                sdcard_read_data (d->fd, d->offset, &d->buf[2], d->blen);
                reply = 0;
            }
            break;
        default:                        /* Ignore */
            break;
        }
    }
Ejemplo n.º 2
0
int main(void) {
  cli();

  /* We need to use a timer to control how long our main loop iterations are.
   * Experiments showed that the main loop was executing approximately every
   * 3.2 milliseconds, which is too quick for the sdcard to write a block
   * of data. Here we are configuring Timer1 because it is a "16-bit" timer
   * which would allow us to count to values greater than (2^8)-1. For a pre-
   * scale value of 64, the timer will count up to 16,000,000/64 = 250,000.
   * This gives us a timer period of 250,000 ticks/sec = 4 microseconds/tick.
   * Suppose we want the main loop to run 40 times per second (40 Hz), we would
   * need to restart the loop when Timer1 reaches the value: 250,000/40 = 6250
   * See Atmel datasheet for Mega, Section 17.11
   */
  TCCR1A = 0b00000000;  // Normal operation; no waveform generation by default
  TCCR1B = 0b00000011;  // No input capture, waveform gen; prescaler = 64
  TCCR1C = 0b00000000;  // No output compare
  TIMSK1 = 0b00000000;

  // TIMING DEBUG - Digital Pin 4
  DDRG |= (1 << 5);

  char msg[64];

  if (button_init() &&
      uwrite_init() &&
      cmps10_init() &&
      sdcard_init()) {
    uwrite_print_buff("All systems go!\r\n");
    return 0;
  } else {
    uwrite_print_buff("There was an error during init\r\n");
    return 1;
  }

  memset(msg, 0, sizeof(msg));
  memset(&statevars, 0, sizeof(statevars));
  statevars.prefix = 0xDADAFEED;
  statevars.suffix = 0xCAFEBABE;

  uint32_t iterations = 0;

  sei();

  TIMSK1 = 0b00000001;

  while (1) {
    // TIMING DEBUG FOR OSCILLOSCOPE
    PORTG |= (1 << 5);

    TCNT1 = 0;

    button_update();
    cmps10_update_all();
    statevars.main_loop_counter = iterations;
    mainloop_timer_overflow = 0;

    // TIMING DEBUG FOR OSCILLOSCOPE
    PORTG &= (0 << 5);

    if (button_is_pressed()) {
      uwrite_print_buff("The button is pressed! The LED should be on.\r\n");
      led_turn_on();
      statevars.mission_started = 1;
    } else {
      led_turn_off();
      statevars.mission_started = 0;
    }

    snprintf(msg, sizeof(msg),
      "Heading: %u  Pitch: %d  Roll: %hhd\r\n",
     cmps10_heading, cmps10_pitch, cmps10_roll); 
     // Needed to cast these values to display negative pitch and roll values
     //(int8_t) statevars.heading_raw, (int8_t) statevars.pitch_deg, (int8_t) statevars.roll_deg); 
    uwrite_print_buff(msg);

    sdcard_write_data();

    iterations++;

    if (iterations > 256) {
      uwrite_print_buff("Finished collecting data!\r\n");
      break;
    }

    /* Ensure that the main loop period is as long as we want it to be.
     * This means (1) triggering the main loop to restart we notice it is 
     * running too long, and (2) performing busy waiting if the instructions
     * above finish before the desired loop duration.
     */
    while (1) {
      if (mainloop_timer_overflow) {
        break;
      }

      if (TCNT1 >= MAINLOOP_PERIOD_TICKS) {
        break;
      }
    }

  }

  return 0;
}