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
Line 
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
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;
16static uint8_t cksum;
17
18static uint16_t readPos;
19static uint8_t bitpos;
20static uint8_t bit; // Currently generated bit
21
22int main() {
23 // Init
24 status = 0;
25 writePos = 0;
26 blksz = 0;
27
28 wdt_enable(WDTO_2S);
29
30 // USB
31 usbInit();
32 sei();
33
34 bit = 1;
35 bitpos = 7;
36 readPos = 0;
37
38 // Generate sync header (this never changes)
39 int i;
40 for (i = 0; i< 16; i++)
41 {
42 ioblock[i] = 1;
43 }
44 ioblock[16] = 0x3C;
45 ioblock[17] = 0x5A;
46
47 // Setup TIMER 1 for MFM pulses generation
48 TCCR1A = (1<<COM1A0); // Enable OC1A output
49 TCCR1A |= (1<<COM1A1); // Compare match will always SET OC1A instead of toggling it. Thus the output is always high.
50 // CTC mode with OCR1A as MAXregister
51 TCCR1B = (1<<WGM12);
52 OCR1A = 13063; // 800us bit clock
53 OCR1B = 6532; // Half-clock for 1 bits
54 TIMSK = (1 << OCIE1B) | (1 << OCIE1A); // interrupts on both timer matches.
55 TCCR1A |= (bit << FOC1A); // Force toggle of A (make sure output is a logic 1 to allow MO5 to detect tapedrive)
56
57 DDRB |= 2; // OC1A/PB1 as output
58
59
60 while(1) {
61 wdt_reset();
62 usbPoll();
63 // TODO watch for motor on/off
64 }
65}
66
67
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
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 */
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 }
109 }
110 }
111 return 0;
112}
113
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 {
119 ioblock[writePos] = data[i];
120 cksum -= data[i];
121 writePos++;
122 }
123
124 ioblock[writePos] = cksum;
125
126 if (writePos >= blksz - 1)
127 {
128 // start generating
129 startGen();
130 return 1;
131 } else {
132 return 0;
133 }
134 // returns 0: "needs more data"
135 // returns 1: "done"
136 // returns FF: "error"
137}
138
139ISR (TIMER1_COMPA_vect, ISR_NOBLOCK)
140{
141 // generate next bit
142 bit = (ioblock[readPos] >> bitpos) & 1;
143 bitpos--;
144 if (bitpos > 7) // overflow ?
145 {
146 bitpos = 7;
147 readPos++;
148 if (readPos > blksz)
149 {
150 // Make sure output is high step 1: match action = force high level
151 TCCR1A |= (1<<COM1A1);
152
153 // Stop generating (and interrupts)
154 TCCR1B &= ~(1<<CS10);
155 readPos = 0;
156
157 // make sure output is high step 2 : force a match.
158 TCCR1A |= (1 << FOC1A);
159 }
160 }
161}
162
163ISR (TIMER1_COMPB_vect, ISR_NOBLOCK)
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.