source: avrstuff/V-USB_Dev/firmwares/CrO2/main.c@ 3c17057

main
Last change on this file since 3c17057 was 3c17057, checked in by Adrien Destugues <pulkomandy@…>, 12 years ago

Fix bugs related to minimal-size blocks. Loading a standard game works !

git-svn-id: svn://pulkomandy.tk/avrstuff@54 c6672c3c-f6b6-47f9-9001-1fd6b12fecbe

  • Property mode set to 100644
File size: 3.7 KB
RevLine 
[1fabcce]1#include <avr/io.h>
2#include <avr/interrupt.h>
3#include <avr/wdt.h>
4#include <avr/pgmspace.h>
5#include <util/delay.h>
6
7#include <string.h>
8#include <stdbool.h>
9
10#include "usbdrv/usbdrv.h"
11
[4af90bf]12static uint8_t ioblock[275]; // Max. Size of an MO5 standard block including sync header
13static uint8_t status; // status bits
14static uint16_t writePos;
15static uint16_t blksz;
[3c17057]16static uint8_t cksum;
[1fabcce]17
[4af90bf]18static uint16_t readPos;
19static uint8_t bitpos;
20static uint8_t bit; // Currently generated bit
[1fabcce]21
[4af90bf]22int main() {
23 // Init
24 status = 0;
25 writePos = 0;
26 blksz = 0;
[1fabcce]27
28 wdt_enable(WDTO_2S);
29
30 // USB
31 usbInit();
32 sei();
33
[4af90bf]34 bit = 1;
[e69146a]35 bitpos = 7;
[4af90bf]36 readPos = 0;
[1fabcce]37
[e07597b]38 // Generate sync header (this never changes)
39 int i;
40 for (i = 0; i< 16; i++)
41 {
42 ioblock[i] = 1;
43 }
[3c17057]44 ioblock[16] = 0x3C;
45 ioblock[17] = 0x5A;
[e07597b]46
[4af90bf]47 // Setup TIMER 1 for MFM pulses generation
48 TCCR1A = (1<<COM1A0); // Enable OC1A output
[e07597b]49 TCCR1A |= (1<<COM1A1); // Compare match will always SET OC1A instead of toggling it. Thus the output is always high.
[4af90bf]50 // CTC mode with OCR1A as MAXregister
[e07597b]51 TCCR1B = (1<<WGM12);
[e69146a]52 OCR1A = 13063; // 800us bit clock
53 OCR1B = 6532; // Half-clock for 1 bits
[4af90bf]54 TIMSK = (1 << OCIE1B) | (1 << OCIE1A); // interrupts on both timer matches.
[e07597b]55 TCCR1A |= (bit << FOC1A); // Force toggle of A (make sure output is a logic 1 to allow MO5 to detect tapedrive)
[4af90bf]56
57 DDRB |= 2; // OC1A/PB1 as output
[1fabcce]58
59
60 while(1) {
61 wdt_reset();
62 usbPoll();
[e07597b]63 // TODO watch for motor on/off
[1fabcce]64 }
65}
66
67
[3c17057]68static inline void startGen()
69{
70 TCCR1A &= ~(1<<COM1A1); // Toggle output on compare match
71 TCCR1B |= (1<<CS10); // Enable timer clock (prescaler = 1)
72}
73
74
[4af90bf]75uint8_t usbFunctionSetup(uint8_t data[8]) {
76 usbRequest_t *rq = (void *)data;
77
78 usbMsgPtr = ioblock;
79 switch(rq->bRequest)
80 {
81 case 0:
82 { /* CONFIGURE */
83 status = rq->wValue.bytes[0];
84 return 0;
85 }
86 case 1:
87 { /* RECEIVE/POLL DATA (TAPE > USB) */
88 return 254;
89 }
90 case 2:
91 {
92 /* SEND DATA (USB > TAPE) */
93 /* Get ready, actual data will come in usbFunctionWrite */
[3c17057]94
95 // store type of MO5 block + size in ioblock
96 writePos = 20; // Leave space for Sync header, block type, and block size.
97 ioblock[18] = rq->wValue.word;
98 ioblock[19] = rq->wLength.word + 2; // Add blktype and cksum to data length
99 blksz = rq->wLength.word + 21;
100 cksum = 0;
101 if (rq->wLength.word == 0)
102 {
103 // No data in this block - start generating now !
104 ioblock[20] = 0; // checksum
105 startGen();
106 } else {
107 return USB_NO_MSG; // Call usbFunctionWrite to send the data
108 }
[4af90bf]109 }
110 }
111 return 0;
112}
[1fabcce]113
[4af90bf]114uint8_t usbFunctionWrite(uint8_t* data, uint8_t len)
115{
116 // The data for a single request will be sent as slices of up to 8 bytes.
117 for (int i = 0; i < len; i++)
118 {
[3c17057]119 ioblock[writePos] = data[i];
120 cksum -= data[i];
[e07597b]121 writePos++;
[4af90bf]122 }
[1fabcce]123
[3c17057]124 ioblock[writePos] = cksum;
[1fabcce]125
[3c17057]126 if (writePos >= blksz - 1)
[e07597b]127 {
128 // start generating
[3c17057]129 startGen();
[e07597b]130 return 1;
131 } else {
132 return 0;
133 }
[4af90bf]134 // returns 0: "needs more data"
135 // returns 1: "done"
136 // returns FF: "error"
[1fabcce]137}
138
[e07597b]139ISR (TIMER1_COMPA_vect, ISR_NOBLOCK)
[4af90bf]140{
141 // generate next bit
142 bit = (ioblock[readPos] >> bitpos) & 1;
[e69146a]143 bitpos--;
144 if (bitpos > 7) // overflow ?
[4af90bf]145 {
[e69146a]146 bitpos = 7;
[4af90bf]147 readPos++;
[e07597b]148 if (readPos > blksz)
149 {
[3c17057]150 // Make sure output is high step 1: match action = force high level
[e07597b]151 TCCR1A |= (1<<COM1A1);
[3c17057]152
[e07597b]153 // Stop generating (and interrupts)
154 TCCR1B &= ~(1<<CS10);
155 readPos = 0;
[3c17057]156
157 // make sure output is high step 2 : force a match.
[e07597b]158 TCCR1A |= (1 << FOC1A);
159 }
[4af90bf]160 }
[1fabcce]161}
162
[e07597b]163ISR (TIMER1_COMPB_vect, ISR_NOBLOCK)
[4af90bf]164{
165 TCCR1A |= (bit << FOC1A); // Force toggle of A on B compare when generating a 1 bit
166}
Note: See TracBrowser for help on using the repository browser.