#include #include #include #include #include #include #include #include "usbdrv/usbdrv.h" static uint8_t ioblock[275]; // Max. Size of an MO5 standard block including sync header static uint8_t status; // status bits static uint16_t writePos; static uint16_t blksz; static uint8_t cksum; static uint16_t readPos; static uint8_t bitpos; static uint8_t bit; // Currently generated bit int main() { // Init status = 0; writePos = 0; blksz = 0; wdt_enable(WDTO_2S); // USB usbInit(); sei(); bit = 1; bitpos = 7; readPos = 0; // Generate sync header (this never changes) int i; for (i = 0; i< 16; i++) { ioblock[i] = 1; } ioblock[16] = 0x3C; ioblock[17] = 0x5A; // Setup TIMER 1 for MFM pulses generation TCCR1A = (1<bRequest) { case 0: { /* CONFIGURE */ status = rq->wValue.bytes[0]; return 0; } case 1: { /* RECEIVE/POLL DATA (TAPE > USB) */ return 254; } case 2: { /* SEND DATA (USB > TAPE) */ /* Get ready, actual data will come in usbFunctionWrite */ // store type of MO5 block + size in ioblock writePos = 20; // Leave space for Sync header, block type, and block size. ioblock[18] = rq->wValue.word; ioblock[19] = rq->wLength.word + 2; // Add blktype and cksum to data length blksz = rq->wLength.word + 21; cksum = 0; if (rq->wLength.word == 0) { // No data in this block - start generating now ! ioblock[20] = 0; // checksum startGen(); } else { return USB_NO_MSG; // Call usbFunctionWrite to send the data } } } return 0; } uint8_t usbFunctionWrite(uint8_t* data, uint8_t len) { // The data for a single request will be sent as slices of up to 8 bytes. for (int i = 0; i < len; i++) { ioblock[writePos] = data[i]; cksum -= data[i]; writePos++; } ioblock[writePos] = cksum; if (writePos >= blksz - 1) { // start generating startGen(); return 1; } else { return 0; } // returns 0: "needs more data" // returns 1: "done" // returns FF: "error" } ISR (TIMER1_COMPA_vect, ISR_NOBLOCK) { // generate next bit bit = (ioblock[readPos] >> bitpos) & 1; bitpos--; if (bitpos > 7) // overflow ? { bitpos = 7; readPos++; if (readPos > blksz) { // Make sure output is high step 1: match action = force high level TCCR1A |= (1<