Gert van der Knokke
/
C1541III
C1541-III mbed edition
Embed:
(wiki syntax)
Show/hide line numbers
IEC_bus.c
00001 /*------------------------------------------------------------------------------------------*/ 00002 /*This is the lowlevel IEC-bus_driver, */ 00003 /* */ 00004 /*Note that this driver is dirty because it polls the drive for it's flags. The */ 00005 /*routines in this driver should therefore only be called from a low priority task */ 00006 /* */ 00007 /*Attention: routines tuned for 20MHz */ 00008 /*------------------------------------------------------------------------------------------*/ 00009 /* History: 00010 -------- 00011 2007-04-28 KeepItSimpleStupid, so hanging on to this live style I removed the 'filter' from the IEC_receive routine (it was unneccessary nonsense anyway) 00012 2007-04-25 CheckForCommand had an delay of 200uS to ensure the "frame to release of ATN'-time" of min 20uS, this is removed and now in the higher level IEC staemachine (main.c) 00013 2007-04-23 IECundoturnaround() was checking for the clok, this is not reuiqed in this situation, that's why the timeout worked bettre then no timeout, simply because the CLOCK check is not required at THIS stage of the communication 00014 2007-04-16 removed a semicolon in the acknowledge timeout check... there should not be a semicolon after the while :-) (oops) 00015 2007-04-15 ADDED a ATN check on IEC_turnaround routine 00016 2007-04-09 removed all code that was made commentary with // 00017 2007-04-08 added the same 'filter' on FreeIEC and CheckForCommand... and then disabled the new code with "//" simply because the new improvements made it even worse... 00018 2007-04-07 added some extra checks to make sure we trigger/test the clock/data signals correctly (software signal filtering). 00019 this is required because sometimes the device triggers incorrectly on signals meant for other devices on the bus 00020 which is best noticable during intense bus trafic. But it is very likely to happen at any moment (you can't predict glitches/spikes). 00021 2007-04-01 the check IEC_CLOCK == 1 in UNDOTURNAROUND now has a time-out, simply to improve reliablillity... it helps a lot! 00022 2006-11-01 the channel value was always extracted from the commandbyte, even if there was no channel value. This caused problems in the new statemachine (before the new statemachine the channel was used before the 3f/5f command so this problme was no problem then) 00023 2006-10-31 added thefunction IEC_monitor this function can be used to monitor bus activity without interfering 00024 removed the setdeviceaddress function, since this is handled in MAIN.C 00025 2006-10-30 the data and open command are identical when the errorchannel (15) is addressed 00026 2006-10-22 changed the channel-variable to a variable outside the IEC_bus code, so it can be used in MAIN.c where it is declared 00027 2006-10-20 added a function to set the timings of the IEC-bus (required for 25% faster VIC20-mode) 00028 2006-07-03 changed 'FreeIEC' routine, this routine caused busylooping at an unwanted level, the busy-loop waiting for ATN going low 00029 is now located in main, so we can do other things while not communicating over the IEC-bus (manual file selection for instance) 00030 2006-07-02 changed WaitForCommand into CheckForCommand, since the routine is no longer a while loop 00031 2006-03-28 change in release and pulldown ATN-line routines, caused by new PCB design 00032 2006-02-22 added frame_handshake signal for later use 00033 2006-02-02 improvements in code layout... i.o.w. making it more readable 00034 2005-10-18 start of IEC bus driver 00035 2005-10-19 further details on EOI condition 00036 2005-10-22 delay routines for IEC timing 00037 2005-10-25 corrected the IEC-receive routine (without EOI detection) 00038 2005-10-26 timeouts and EOI handling 00039 2005-10-27 bus turnaround routines and testing of write routines. Optimisation of the send routines 00040 2006-01-04 added IEC_send_string, is much more convinient then printf 00041 2006-01-10 TALK and LISTEN definitions were mixed up, is corrected. FreeIEC-routine added and improved 00042 2006-01-13 adjusted delay in waitforcommand routine, now external devices work 00043 2006-01-16 rewritten the waitforcommand routine 00044 */ 00045 00046 /* TO DO: 00047 ------ 00048 - EOI acknowledge delay, set/test this to correct timings for 20MHz 00049 00050 */ 00051 00052 /*------------------------------------------------------------------------------------------*/ 00053 00054 /*--------------------------------------------------------*/ 00055 /* includes */ 00056 /*--------------------------------------------------------*/ 00057 #include <mbed.h> 00058 00059 #include <stdio.h> 00060 #include <IEC_bus.h> 00061 #include <delay.h> 00062 #include <hardware.h> 00063 00064 /*--------------------------------------------------------*/ 00065 /* constants */ 00066 /*--------------------------------------------------------*/ 00067 #define FALSE 0 /*FALSE*/ 00068 #define TRUE 1 /*TRUE*/ 00069 00070 /*--------------------------------------------------------*/ 00071 /* globals */ 00072 /*--------------------------------------------------------*/ 00073 unsigned char IEC_receive_delay; /*set delay to ..uSec*/ 00074 unsigned char IEC_send_delay; /*set delay to ..uSec*/ 00075 00076 /*external variables (variables also used in other .c files)*/ 00077 /*external variables (variables also used in other .c files)*/ 00078 extern bit EOI; /*End Of Indicator: this flag (when TRUE) indicates that the last byte is being transmitted or received*/ 00079 extern bit TimeOut; /*Timeout-flag*/ 00080 extern unsigned char channel; /*this register holds the channel value*/ 00081 00082 /*--------------------------------------------------------*/ 00083 /* local functions */ 00084 /*--------------------------------------------------------*/ 00085 00086 00087 /*--------------------------------------------------------*/ 00088 /* external functions */ 00089 /*--------------------------------------------------------*/ 00090 00091 //IEC_ATN : when IEC_ATN=0 it means that all devices must switch to listen (receive) mode immediatly 00092 00093 00094 /*set all IEC_signal lines in the correct mode*/ 00095 void InitIEC(void) 00096 { 00097 SetIEC_timings(TIMINGS_DEFAULT); /*set timings according the default settings (C64 compatible mode)*/ 00098 IEC_ATN_REL(); 00099 IEC_CLOCK_REL(); 00100 IEC_DATA_REL(); 00101 IEC_SRQ_REL(); 00102 EOI = FALSE; 00103 TimeOut = FALSE; 00104 } 00105 00106 void SetIEC_timings(unsigned char settings) 00107 { 00108 switch(settings) 00109 { 00110 case TIMINGS_VIC20: /*Timings for VIC-20 mode*/ 00111 { /*-----------------------*/ 00112 IEC_receive_delay = 52; /*set delay to ..uSec*/ 00113 IEC_send_delay = 60; /*set delay to ..uSec*/ 00114 break; 00115 } 00116 00117 case TIMINGS_DTV: /*Timings for DTV (tuned IEC-bus speeds)*/ 00118 { /*--------------------------------------*/ 00119 IEC_receive_delay = 60; /*set delay to ..uSec*/ 00120 IEC_send_delay = 80; /*set delay to ..uSec*/ 00121 break; 00122 } 00123 00124 default: /*Timings according (C64) IEC-specs*/ 00125 { /*---------------------------------*/ 00126 IEC_receive_delay = 70; /*set delay to ..uSec*/ 00127 IEC_send_delay = 80; /*set delay to ..uSec*/ 00128 break; 00129 } 00130 } 00131 } 00132 00133 /*free the IEC bus for use by other devices, the bus is free'd until ATN is released*/ 00134 void FreeIEC(void) 00135 { 00136 IEC_ATN_REL(); 00137 IEC_CLOCK_REL(); 00138 IEC_DATA_REL(); 00139 while(IEC_ATN() == 0); 00140 } 00141 00142 00143 /*this routine will wait untill it receives one byte over the IEC-bus*/ 00144 unsigned char IEC_receive(unsigned char frame_handshake) 00145 { 00146 unsigned char data; 00147 unsigned char bitcount; 00148 unsigned long t; 00149 00150 EOI = FALSE; /*clear the EOI flag*/ 00151 TimeOut = FALSE; /*clear the timeout flag*/ 00152 data = 0; /*clear destination register*/ 00153 bitcount = 8; /*the number of bits within a byte are still eight*/ 00154 00155 /*-----Step1:Ready to send--------------------------------------------------------------------------------*/ 00156 while (IEC_CLOCK() == 0); /*wait (endlessly) until we see some action on the bus, we may respond whenever we please*/ 00157 00158 /*Step2:Ready for data--------------------------------------------------------------------------------*/ 00159 IEC_DATA_REL(); /*response to talker READY FOR DATA, this signal has no time-limit since we may be busy formatting a disk or printing out a chunk of text to paper*/ 00160 00161 /*-----intermission:EOI--------------------------------------------------------------------------------*/ 00162 t = 5000; /*timeout value for detecting an EOI condition*/ 00163 while (IEC_CLOCK() == 1) /*wait for the talker to indicate that the transmission will start (this signal must be received within 200uS, otherwise we may consider it as an EOI)*/ 00164 { 00165 t--; /*when timed out, we have detected an EOI condition*/ 00166 if (t == 0) /*timeout detected ?*/ 00167 { 00168 EOI = TRUE; /*set the EOI flag*/ 00169 IEC_DATA_PULL(); /*acknowledge the EOI condition*/ 00170 DelayBigUs(IEC_receive_delay); /*delay for .. uSec*/ 00171 IEC_DATA_REL(); /*acknowledge the EOI condition*/ 00172 } 00173 } 00174 00175 /*-----Step3:receiving the bits--------------------------------------------------------------------------------*/ 00176 while (bitcount != 0) /*data is received with LSB first*/ 00177 { 00178 data>>=1; /*shift the byte one bit to the right*/ 00179 bitcount--; /*decrement bitcounter by one*/ 00180 t = 5000; /*timeout value*/ 00181 while (IEC_CLOCK() == 0); /*wait for the talker to release the clock line to signal "bit ready"*/ 00182 { 00183 t--; /*timeout detection is required to prevent "hanging" in case of data transmission erros*/ 00184 if (t == 0) /*timeout detected ?*/ 00185 { 00186 TimeOut = TRUE; /*set the timeout flag*/ 00187 return(0); /*exit*/ 00188 } 00189 } 00190 00191 if (IEC_DATA() == 1) /*test if bit is set or cleared (attention:documentation states that signals are inverted ?!?! error ?!?!*/ 00192 data = data + 128; /*make bit 7 high*/ 00193 00194 t = 5000; /*timeout value*/ 00195 while (IEC_CLOCK() == 1); /*wait for the talker to pulldown the clock line*/ 00196 { 00197 t--; /*timeout detection is required to prevent "hanging" in case of data transmission erros*/ 00198 if (t == 0) /*timeout detected ?*/ 00199 { 00200 TimeOut = TRUE; /*set the timeout flag*/ 00201 return(0); /*exit*/ 00202 } 00203 } 00204 } 00205 00206 /*-----Step4:frame handshake--------------------------------------------------------------------------------*/ 00207 if (frame_handshake == FALSE) /*we must acknowledge within 1 mS that we have received the data, if not the talker knows there is something wrong*/ 00208 DelayBigUs(1250); /*delay for more then 1000 uSec*/ 00209 00210 IEC_DATA_PULL(); 00211 return(data); /*exit with the received data*/ 00212 } 00213 00214 00215 /*this routine will send one byte over the IEC-bus*/ 00216 unsigned char IEC_send(unsigned char data) 00217 { 00218 unsigned char bitcount; 00219 unsigned long t; 00220 bitcount = 8; /*the number of bits within a byte are still eight*/ 00221 TimeOut = FALSE; /*clear the timeout flag*/ 00222 00223 /*-----Step1:Ready to send--------------------------------------------------------------------------------*/ 00224 00225 IEC_CLOCK_REL(); /*indicate to the listener that we are ready to send*/ 00226 00227 /*-----Step2:Ready for data--------------------------------------------------------------------------------*/ 00228 while (IEC_DATA() == 0); /*wait for the listener (computer) to release the data-line (ready to receive data), this may take forever... (according the IEC-bus definition)*/ 00229 00230 /*intermission:EOI--------------------------------------------------------------------------------*/ 00231 if (EOI == TRUE) 00232 { 00233 DelayUs(200); /*delay for more then 200 uSec*/ 00234 t = 5000; /*timeout value*/ 00235 while (IEC_DATA() == 1); /*check for acknowledge of the EOI. The acknowledge is simply pulling the data-line down for a brief period*/ 00236 { 00237 t--; /*timeout detection is required to prevent "hanging" in case of data transmission erros*/ 00238 if (t == 0) /*timeout detected ?*/ 00239 { 00240 TimeOut = TRUE; /*set the timeout flag*/ 00241 return(FALSE); /*exit*/ 00242 } 00243 } 00244 t = 5000; /*timeout value*/ 00245 while (IEC_DATA() == 0); /**/ 00246 { 00247 t--; /*timeout detection is required to prevent "hanging" in case of data transmission erros*/ 00248 if (t == 0) /*timeout detected ?*/ 00249 { 00250 TimeOut = TRUE; /*set the timeout flag*/ 00251 return(FALSE); /*exit*/ 00252 } 00253 } 00254 /*EOI is acknowledged by the listener (computer)*/ 00255 } 00256 IEC_CLOCK_PULL(); /*indicate to the listener (computer) that the transmission will start*/ 00257 DelayUs(IEC_send_delay); /*delay for .. uSec*/ 00258 00259 /*-----Step3:receiving the bits--------------------------------------------------------------------------------*/ 00260 while (bitcount != 0) /*data is transmitted with LSB first*/ 00261 { 00262 IEC_CLOCK_PULL(); /*release the clockline in order to set the next bit on the data-line*/ 00263 DelayUs(IEC_send_delay); /*delay for .. uSec*/ 00264 bitcount--; 00265 if (data & 0x01) 00266 { 00267 IEC_DATA_REL(); 00268 } 00269 else 00270 { 00271 IEC_DATA_PULL(); 00272 } 00273 IEC_CLOCK_REL(); /*indicate to the listener (computer) "bit ready"*/ 00274 data>>=1; /*shift the byte one bit to the right*/ 00275 DelayUs(IEC_send_delay); /*delay for at least 60uSec when a C64 is listening*/ 00276 } 00277 IEC_CLOCK_PULL(); /*the whole byte has been transmitted*/ 00278 DelayUs(IEC_send_delay); /*delay for at least 60uSec when a C64 is listening*/ 00279 IEC_DATA_REL(); /*set clock and data in the correct order and wait for an acknowledge*/ 00280 DelayUs(25); /*wait a few uSec to prevent a false trigger*/ 00281 00282 /*----Step4:frame handshake--------------------------------------------------------------------------------*/ 00283 t = 5000; /*timeout value*/ 00284 while (IEC_DATA() == 1) /*wait for the listener (computer) to acknowledge this byte it must respond within 1 mSec*/ 00285 { 00286 t--; /*timeout detection is required to prevent "hanging" in case of data transmission erros*/ 00287 if (t == 0) /*timeout detected ?*/ 00288 { 00289 TimeOut = TRUE; /*set the timeout flag*/ 00290 return(FALSE); /*exit*/ 00291 } 00292 } 00293 DelayUs(100); /*time between bytes is according IEC-specs at least 100 uSec*/ 00294 return(TRUE); /*the byte has been succesfully transmitted*/ 00295 } 00296 00297 00298 /*this routine will wait untill it receives one byte over the IEC-bus*/ 00299 /*this routine does NOT generate any signals, it only listens... */ 00300 unsigned char IEC_monitor(void) 00301 { 00302 unsigned char data; 00303 unsigned char bitcount; 00304 unsigned long t; 00305 00306 EOI = FALSE; /*clear the EOI flag*/ 00307 TimeOut = FALSE; /*clear the timeout flag*/ 00308 data = 0; /*clear destination register*/ 00309 bitcount = 8; /*the number of bits within a byte are still eight*/ 00310 00311 /*-----Step1:Ready to send--------------------------------------------------------------------------------*/ 00312 while (IEC_CLOCK() == 0); /*wait (endlessly) until we see some action on the bus, we may respond whenever we please*/ 00313 00314 /*-----intermission:EOI--------------------------------------------------------------------------------*/ 00315 t = 5000; /*timeout value for detecting an EOI condition*/ 00316 while (IEC_CLOCK() == 1) /*wait for the talker to indicate that the transmission will start (this signal must be received within 200uS, otherwise we may consider it as an EOI)*/ 00317 { 00318 t--; /*when timed out, we have detected an EOI condition*/ 00319 if (t == 0) /*timeout detected ?*/ 00320 EOI = TRUE; /*set the EOI flag*/ 00321 } 00322 00323 /*-----Step3:receiving the bits--------------------------------------------------------------------------------*/ 00324 while (bitcount != 0) /*data is received with LSB first*/ 00325 { 00326 data>>=1; /*shift the byte one bit to the right*/ 00327 bitcount--; /*decrement bitcounter by one*/ 00328 t = 5000; /*timeout value*/ 00329 while (IEC_CLOCK() == 0); /*wait for the talker to release the clock line to signal "bit ready"*/ 00330 { 00331 t--; /*timeout detection is required to prevent "hanging" in case of data transmission erros*/ 00332 if (t == 0) /*timeout detected ?*/ 00333 { 00334 TimeOut = TRUE; /*set the timeout flag*/ 00335 return(0); /*exit*/ 00336 } 00337 } 00338 00339 if (IEC_DATA() == 1) /*test if bit is set or cleared (attention:documentation states that signals are inverted ?!?! error ?!?!*/ 00340 data = data + 128; /*make bit 7 high*/ 00341 00342 t = 5000; /*timeout value*/ 00343 while (IEC_CLOCK() == 1); /*wait for the talker to pulldown the clock line*/ 00344 { 00345 t--; /*timeout detection is required to prevent "hanging" in case of data transmission erros*/ 00346 if (t == 0) /*timeout detected ?*/ 00347 { 00348 TimeOut = TRUE; /*set the timeout flag*/ 00349 return(0); /*exit*/ 00350 } 00351 } 00352 } 00353 return(data); /*exit with the received data*/ 00354 } 00355 00356 00357 /*this routine will handle strings, for sending strings over the IEC-bus*/ 00358 void IEC_send_string(const unsigned char *inputstring) 00359 { 00360 unsigned char lp; 00361 00362 lp = 0; 00363 while(inputstring[lp] != 0) 00364 { 00365 IEC_send(inputstring[lp]); 00366 lp++; 00367 } 00368 } 00369 00370 void IEC_send_number_as_ASCII(unsigned char number) 00371 { 00372 unsigned char i; 00373 00374 i = 0x30 + (number/10); /*10's of the value*/ 00375 IEC_send(i); 00376 i = 0x30 + (number%10); /*1's of the value*/ 00377 IEC_send(i); 00378 } 00379 00380 /*this routine will reverse the direction of the bus*/ 00381 void IEC_turnaround(void) 00382 { 00383 while (IEC_ATN() == 0); /*wait (endlessly) until the computer releases ATN*/ 00384 while (IEC_CLOCK() == 0); /*wait (endlessly) until the computer releases the clock line*/ 00385 IEC_DATA_REL(); 00386 DelayUs(25); /*small delay... to make the timing look like the timing of a real drive*/ 00387 IEC_CLOCK_PULL(); 00388 DelayUs(160); /*Tda = 80 uSec minimum acknowledge time for acknowledging the device is now a talker*/ 00389 } 00390 00391 00392 /*this routine will set the direction on the bus back to normal (the way it was when the computer was switched on)*/ 00393 void IEC_undoturnaround(void) 00394 { 00395 // unsigned int timeout_cnt; 00396 // DelayUs(50); /*Talk-Attention release (max. 100uS)*/ 00397 IEC_DATA_PULL(); 00398 IEC_CLOCK_REL(); 00399 DelayUs(25); /*small delay for .. uSec in order to prevent a false trigger*/ 00400 // timeout_cnt = 0; 00401 // while (IEC_CLOCK() == 1) /*wait until the computer pulls down the clock line or we timeout*/ 00402 // { 00403 // if (timeout_cnt == 1000) 00404 // break; /*timeout exceeded, leave routine*/ 00405 // else 00406 // timeout_cnt++; 00407 // } 00408 } 00409 00410 /*this routine will let the bus lines go, as Jim Butterfield described, both talker and listener 'letgo'*/ 00411 void IEC_letgo(void) 00412 { 00413 DelayUs(50); /*after a suitable pause*/ 00414 IEC_DATA_REL(); /*dataline and clockline are released*/ 00415 IEC_CLOCK_REL(); 00416 } 00417 00418 extern DigitalOut(myled3); 00419 00420 unsigned char CheckForCommand(unsigned char *outputcommand, unsigned char frame_handshake) 00421 { 00422 if(IEC_ATN() == 1) /* wait untill there is relevant info (a command is indicated by the attention signal) on the bus */ 00423 { 00424 IEC_DATA_REL(); /*free the bus... (if not allready released)*/ 00425 return(FALSE); /*no command received, yet...*/ 00426 } 00427 00428 IEC_DATA_PULL(); /*join the bus...*/ 00429 *outputcommand = IEC_receive(frame_handshake); /*save the received command to a register specified by the caller of this routine*/ 00430 if ((TimeOut == FALSE) && (IEC_ATN() == 0)) 00431 { 00432 if (*outputcommand == UNLISTEN) /*check for command:UNLISTEN, device:..., Attention-line must still be active*/ 00433 return(UNLISTEN); 00434 00435 if (*outputcommand == UNTALK) /*check for command:UNTALK, device:..., Attention-line must still be active*/ 00436 return(UNTALK); 00437 00438 if ((*outputcommand & 0xF0) == DATA) /*check for command:DATA, channel:..., Attention-line must still be active*/ 00439 { 00440 channel = *outputcommand & 0x0F; /*(if send) the channel is stored in the low-nibble of the command*/ 00441 return(DATA); 00442 } 00443 00444 if ((*outputcommand & 0xF0) == CLOSE) /*check for command:CLOSE, channel:..., Attention-line must still be active*/ 00445 { 00446 channel = *outputcommand & 0x0F; /*(if send) the channel is stored in the low-nibble of the command*/ 00447 return(CLOSE); 00448 } 00449 00450 if ((*outputcommand & 0xF0) == OPEN) /*check for command:OPEN, channel:..., Attention-line must still be active*/ 00451 { 00452 channel = *outputcommand & 0x0F; /*(if send) the channel is stored in the low-nibble of the command*/ 00453 return(OPEN); 00454 } 00455 00456 return(*outputcommand); /*when none of the above... it's for another device, return the entire command for further analasys*/ 00457 } 00458 return(FALSE); /*code should never reach this point!!!*/ 00459 } 00460 00461 00462 /*--------------------------------------------------------*/ 00463 /* local functions */ 00464 /*--------------------------------------------------------*/ 00465 00466 00467 00468 00469 /* 00470 The person who writes their sourcecode without comments is either very smart or very stupid 00471 */
Generated on Tue Jul 26 2022 04:14:07 by 1.7.2