#ifndef _comcs_h_ #define _comcs_h_ /* a little bit explanations: the comcs-softinterface uses the two 74hc374 latches on the elboard. The c167-side reads the output of the unc20-sided 374, using this OE, and the unc20-side reads the output of the c167-sided outpot, using this OE. Both writes to their own's 374, using the CLK-pin. So every side can write to the 374-internal-latches, and the other side can open the output, to read the contents. ( Note: The using of OE, have no affect to the internal contents of the latches, and latching datas is possible every time with CLK ). For using no additional signals for handshaking, we use only the lower 7 bits for data, and bit 8 for handshaking. The latches are not pulled up, so after startup there is no generally 0xff, normalize 00xff instead. But this is not generally sure, because the first datas written to the unc20-side 374 ( 0xff ) is done by loading the elapp.o - driver. On c167-side after bootup, the rombased c167-base is started, which is in every case earlier then the long booting linux ( nearly 13 sec. ) So for unc20-side it's clear that it's input is in a stable state ( 0xff ). On c167-side, especially for the c167-base, that's not generally sure. Normally, we think that the c167-sided programs acts as slaves for the unc20-sided programs, - or as standalone programs. So c167-sided programs do normally not init the communication, instead this is done by the unc20-sided programs. This makes also sense, because the loading ( especially, the booting ) of the unc20-programs takes much more time, then the starting ( also booting ) of the c167-sided stuff. The generally idea is to have a no-pull-down communication, which means, The receiver has not generally to answer directly of a response, or command from the other side. This makes sense especially for the c167-sided programs, which perhaps has to steer some special stuff outside an interrupt, or acting in a time-sensitive way. What ever, - there are a lot of reasons, to decide for every application-pair, on which commands the receiver has to act directly, and on which commands not. So, the generally rule for a communication is that the sender has to wait for the receiver, till this accepts the receiving. The sender have to know if he has the time to send, and if an answer needed, to wait for it. For messaging the receiver, that a request is needed, is done by setting the outport to a one byte shoot-command, then waiting for the answer ( if needed ). Rule for sending more than a shootcommand ( a string-command f.exmpl ): Sender sets messagebyte, then waiting till receiver is ready to receive ( byte for byte ). Receiver acts on messagebyte, if he have time, then receiving bytes. The basically concept, is that every side have run a one-comand receiver-function inside their own main-loop. This only looks for the input-port, if it is 0, or 0xff, and if so, it returns directly returning 0. ( means do nothing ). If there a valid message, function handles directly the operations of what to do with the message. These are normally stuff, like handling receiving of string/value/binary commands, and the application- depending hard-stuff-operations, like ending program, booting .... If one side have no time for communications, the function is not called. So this function ( we name it comcs_lookup ), can be set to all points, the time is available for communications. Normally this is done f. exmpl. in a mainloop, after the time-sensitive works. Two of the escpecially messages, are the start of communication, and the ending. All receiver, and sender-functions looks if a communication is valid. ( Depends on the different start,and ending times on both sides ). The side with the slower startup-times has to start the communication with a special function ( comcs_start ). These function waits with a useable timeout till the comcs_lookup detects the start-message, and answers to it. Normally the unc20-sided programs uses this comcs_start once a time on startup, and the comcs_lookup on c167-side acknowledges it. On program-end a comcs_end, or comcs_programend should be used. The 7'th bit: ( We use bit bit0 - bit7, not bit 1 - bit8 :-). Beneath 0x00, and 0xff, this implementation of comcs_lookup ignores also all messagebytes on the inputport, where bit 7 is not high, and bit6,5,4 is not low. So a valid command is only 1000XXXX ( max 14 commands valid ). The generally difference between bit7( high), and bit 6( low ) depends on the saverness, not to act to unstable inputs, or other unstable states. ( All communications, receive, and send operations should be end with a 0xff ). This should be also used for additional, or other implementations of comcs_lookup like functions. The usage of bit5, and bit4 is reserved for additonal functions like comcs_lookup, which should act only: if not 0x00,0xff, bit7=high,bit6=low, and bit5,and/or bit4 high. bit7 is used for all following transfers. So the ordering is like this: ( On startup, and at end of all operations the outputport has to be set to 0xff ). > Sender waits till in-port is 0xff > then sends message 1000XXXX with one of the functionality dependend functions as first byte. If there are following datas to send ( mostly): > Sender waits till inport shows a 0x01 ( bit 7 also low ) > Sender sets byte with out-bit7 = low. ( if binary data will be send, take high->low order ) > Sender waits till inport shows a 0xff ( bit 7 also high ) > Sender sets output to 0xff, (which takes bit7 also high ) On receiver side following will be done: > comcs_lookup detects a 0x00,0xff, or a (( input & 0xf0(11110000))!= 0x80(10000000) ) it returnes with 0 ( COMCS_LOOKUP_NOTHING ) > If it is another invalid message, output is set to 0xff, and it returnes with 0. > If it is a valid message, which avoids no additional datas, output will be set to 0xff, work will be done, and comcs_lookup returnes the returnvalue for this command. ( For example COMCS_LOOKUP_END ). > If there are message-dependend additional datas to receive, this will be done in following order: > Receiver sets outport to 0x01 ( which sets also bit 7 low ) > Receiver waits till in-bit7 goes low > If so, gets inport as databyte, and stores it. > Receiver sets outport to 0xff ( which sets also bit 7 high ) > Receiver waits till inport shows a 0xff So, with this, we have an allways stable state of communication. Receiver, and Sender has to know exactly the number of bytes to transfer, for the different possiblilities. binary datas, will be handled directly by deassembling the byte to a highbyte >> 4, lowbyte, and sending it in this order. receiver also receives first highbyte, then lowbyte, assembles it to a byte before storing it. */ #ifdef ELAPP_C167 #include #include #include #include #include "asmutil.h" #define CS_COMCS 0x088000 #define CSCOMCS_W MVAR(unsigned char,CS_COMCS) #define CSCOMCS_R MVAR(unsigned char,CS_COMCS) #else #include #define CS_COMCS elunc_c167port #define CSCOMCS_W *elunc_c167port #define CSCOMCS_R *elunc_c167port #endif /* --------------------------------------------------- Receive, and return-values for comcs_lookup The following COMCS_LOOKUP_XXXX definitions are the message-codes where comcs_lookup acts for, and also will be send as first byte by the message-dependend send-functions. Also this values are dependend on the functionality will be returned by comcs_lookup. ---------------------------------------------------- */ /* This is only a return-value, no message-code. if invalid, unusable or nothing on port nothing will be done */ #define COMCS_LOOKUP_NOTHING 0x00 /* message-code normally also the return-value Because normally the c167-side programs, are slaves of the unc20-sideed programs, this should used only on c167-side. But, for special cases, this acts also on unc20-side. So, be sure, that in normal cases, the c167-side program do not send a comcs_start, during the boot-time of both sides. On unc20-side a communication is normally started, and the success returned by comcs_start. On c167-side a communication is normally valid after received this by comcs_lookup. If a c167-sided comcs_lookup receives this, internally comcs_available will set, and furthermore communication is valid, till a COMCS_LOOKUP_ENDS is received, or a COMCS_LOOKUP_PROGRAMEND. * If comcs_available is set, comcs_lookup returns COMCS_LOOKUP_NOTHING, and returns, by setting outputport to 0xff. If comcs_available not set, it sends a COMCS_LOOKUP_STARTS by itselfs, and holds it for ~ 50 ms. Then port will be set to 0xff. COMCS_LOOKUP_STARTS is returned. */ //10000001 #define COMCS_LOOKUP_STARTS 0x81 /* message-code return-value after this in comcs_cmd[0] is a single binary value as single command is stored. ( can also be used for transfering keyboardstuff from one side to other) So for this exactly 3 bytes are transferred. the command, highbyte, lowbyte (In comcs_cmd the assembled binary value is be stored ) */ //10000010 #define COMCS_LOOKUP_CMD 0x82 /* message-code return-value in the bytearray comcs_cmd is a 0 terminated string stored. first byte is command, second byte is parameter and then max 128 chars string. Have a look, that this is faster then COMCS_LOOKUP_CMDBIN, because we use not the high,low order for transfering. 128 bytes are directly transfered. ( But only 0-7f peer byte ). */ //10000011 #define COMCS_LOOKUP_CMDSTR 0x83 /* message-code return-value in the bytearray comcs_cmd is binary stuff stored first byte is the command second is the length of following max 128 bytes. ( for 128 binary databytes 256 bytes will be transfered, - in comcs_cmd are the assembled binary values stored. ) */ //10000100 #define COMCS_LOOKUP_CMDBIN 0x84 /* message-code return-value Normally this is used on c167-side, but for special-cases, where the c167-side programm have to break a current communication, this acts also on this side. Communication is no more valid this should be used, instead COMCS_LOOKUP_PROGRAMEND, if an elapp communicates with the c167-base, without an previous send ramprog. So, this preserves the c167 going into nothing. This sets outputport to COMCS_LOOKUP_ENDS for 50 ms, then to 0xff. */ //10000101 #define COMCS_LOOKUP_ENDS 0x85 /* message-code return-value this is only used on c167-side by base ( the rombase-prog ) this avoids a intel-hexfile string, and stores it to the ramspace, avoiding this is a startable prog. This is normally used, when a ram-program is loaded. generally this should be preferred for (0x3a is the char ':' which must be the first char in every string) */ //10000110 #define COMCS_LOOKUP_STRH86 0x86 /* message-code return-value ends communication directly sets outputport to COMCS_LOOKUP_PROGRAMEND for 50 ms, then to 0xff. Then it returns COMCS_LOOKUP_PROGRAMEND. After getting this message, the applications have to do the following now. ( Standartmodel, see more at sending function comcs_send_programend ) c167 base ( rom ) reset to rrspec_ramstart. The unc20-side has to send a correct program with COMCS_LOOKUP_STREAM/H86 before. c167 app ( ramprog ) reset to rrspec_normal, which starts the base-app from rom. unc20 elapp ( the apploader ) nothing unc20 app ( an loaded elapp ) ending programm, and normally recall the apploader elapp */ //10000111 #define COMCS_LOOKUP_PROGRAMEND 0x87 /* ---------------------- the receiver functions ---------------------- */ /* the generally function, which should be used in both sides in the normally mainloop it looks, if the other is available, or send something if there is only a 0xff, or 0 on port which means the other is not valid, or has no stuff to send, then it returns immediately with 0 ( COMCS_LOOKUP_NOTHING ). all other stuff will be handled by this function. the returnvalues depends on the type of receive. see the definitions COMCS_LOOKUP_X */ extern unsigned char comcs_cmd[132]; extern unsigned char comcs_lookup(void); /* ---------------------- init and variables ---------------------- */ /*all sendings, excepting the i' am here are only possible if this is not 0 (do not change this variable by your own) */ extern int comcs_available; /* this is a temporary-value which shows if a timeout occured. Normally, if this is set, no more communication is valid: (do ot change this variable by your own ) */ extern int comcs_timeout; //this sets only the output-port to 0xff, //and should be called at startup of program, //as early, as possible.( Before comcs_start ). #define comcs_init CSCOMCS_W=0xff /*this should be used once a time after startup. It shows the other side, ( normally the c167-slaveapps) that you are available. ( Only if comcs_available not set currently ). Because the c167-side apps normally slaves of unc20-elapps, or standalone programs, comcs_start should used only for unc20-side programs. if both sides calls this during booting, or loading programs on both sides, this can be end in a endless loop. (comcs_lookup acts as receiver for this) If should a c167-side program act as master, the communication first have to be init with a comcs_start on unc20-side. * If commcs_available is set previous, function returns with 1, without any acting. Otherwise, it sends a COMCS_LOOKUP_STARTS, then waits for max ~ 5 seconds seconds, if a COMCS_LOOOKUP_STARTS if received back. If times out, it sets port to 0xff, and returnes 0. If ok, sets port to 0xff, then it waits again, but only for max 500 ms. till inport-port receives a 0xff. If times out, it returns with 0. If received all in time, sets comcs_available to 1, and returns 1. * This avoids, that receiver comes up to call comcs_lookup, inside 5 seconds, what normally on c167-side is available. Again, in normal cases, use this only on unc20-side, and call it not on c167-side. */ extern int comcs_start( void ); /*this should be called, before ending your program it tells the other, that your are no more available, or willing to send. it will only act, if a valid communication is present. This is the alternative to comcs_send_programend, for the special cases, you will not end the peers-program, but setting both ports to a valid 0xff state. A comcs_start can reconnect the communication. If comcs_available not set it returns with 1, and nothing will be done. Otherwise a COMCS_LOOKUP_END is set, Then it waits max ~ 5sec till a COMCS_LOOKUP_END appeares on input port. After this waiting output is set to 0xff in every case. If times out it returnes 0. If ok, waits max 500 ms, till input-port changes to 0xff. If this times out returnes with 0, otherwise with 1. comcs_available will be set to 0 in every case. */ extern int comcs_end( void ); /* ---------------------- the sender functions ---------------------- */ /* the send-command functions */ extern int comcs_send_cmd( unsigned char cmd ); extern int comcs_send_strcmd( unsigned char cmd, unsigned char param, unsigned char *buf ); extern int comcs_send_bincmd( unsigned char cmd, unsigned char len, unsigned char *buf ); /* be sure, what to do, before using this. This is the generally switching between the program in rom, to program in ram, or from ram, to program to rom. Normally if the c167-base is running and the unc20-base ( the programloader elapp ), on unc20 side the elapp perhaps has to load an elapp-program, which needs the communication with a c167-sided program special made for this unc20-application. In this standart procedure, the unc20-base sends the c167-app as hexfile with comcs_send_h86file and then sends comcs_send_programend, or uses comcs_send_h86file_and_start, which calles this function after sending direct, - before loading the elapp-application. The c167-base then should switch to received progam in the ramsegment. Otherwise, the subapplication ( loaded by elapp ) on unc20-side should switch c167 back to c167-base in rom, before reloading its own programloader elapp. The previous versions of comcs_lookup has done the jmps to the segments directly. But there are such a lot of possible variations, and, - much more important, the need of cleanup-work, before ending a program, - sow now comcs_lookup returns the COMCS_LOOKUP_PROGRAMEND, and avoids that the application do the right stuff by itself. * If comcs_available not set, it returns with 0, and nothing will be done. Otherwise a COMCS_LOOKUP_PROGRAMEND is set, Then it waits max ~ 5sec till a COMCS_LOOKUP_PROGRAMEND appeares on input port. After this waiting output is set to 0xff in every case. If times out it returnes 0. If ok, waits max 500 ms, till input-port changes to 0xff. If this times out returnes with 0, otherwise with 1. comcs_available will be set to 0 in every case. */ extern int comcs_send_programend( void ); #ifdef ELAPP_UNC20 /* sends a intel-hexfile, using COMCS_LOOKUP_STRH86 (be sure c167-base is running, before sending this) */ extern int comcs_send_h86file( char *filename ); /* call this from your elapp ( normally only elapp-main, - the programloader ) to send the c167-base a ramprog, and then start it. After this the new elapp communicating with this c167-ramprog is started from elapp, but in special cases this is also valid from an elapp-app. (be sure, c167-base is running, before sending this) this function calls first comcs_sendh86str, then comcs_send_programend. */ extern int comcs_send_h86file_and_start( char *filename ); #endif /* some cmds currently understand by ELAPP_C167_BASE */ //c167-base accepts a COMCS_CMDBIN_SETTIME //in a COMCS_LOOKUP_CMDBIN, //and a COMCS_CMD_GETTIME in a COMCS_LOOKUP_CMD. //After a COMCS_CMD_GETTIME the c167-base sends a //COMCS_CMDBIN_SETTIME like the following //binary structure. //uchar cmd = COMCS_CMDBIN_SETTIME //uchar len = 14 // int year ( 2003 f.exmpl) // int month ( 1 - 12 ) // int day ( 1 - 31 ) // int hour ( 0 - 23 ) // int minute ( 0 - 59 ) // int second ( 0 - 59 ) // int msecond ( 0 - 999 ) //if the c167-base receives a SETTIME, it sets //time only by this, and nothing will be send //bak. ( note the c167 does not accept the //msecond, so send this from unc20-side as //a value whatever you want.= // //so unc20-side which sends a GETTIME, have //to understand also the SETTIME. #define COMCS_CMD_GETTIME 0x01 #define COMCS_CMDBIN_SETTIME 0x01 //following command should be //accepted by every c167,unc20 //sided program. #define COMCS_CMD_REBOOT 0x02 //for activating it, comcs //provides following command void system_reboot(void); //if a connection is available //it sends directly COMCS_CMD_REBOOT //to the peer. //If no connection is open, //it tries to open it before. //After this the own system dependend //reboot-command is called. //if this is used, normally both //systems should to reboot //completely like a hard-reset. //if a COMCS_CMD_REBOOT not //handled by a application-own //comcs_do_cmd only the //caller of system_reboot will //be rebooted, and the other //side unstable. /* internal low-level functions */ //this is a little loop ~ 1/10 ms long //for both,- c167-side, and unc20-side. //Its is used for internal timeouts, //but perhaps also usefull for others. //its not really ecact, so a value //of 10000 for nr, must not exceed //exactly to 1 second. extern void loop1_10ms( unsigned int nr ); //attentions, this is an internally low-level functions //used by comcs_start,end, programend. //It does not test for comcs_available, so you have to //know what you do when you will use it. //First it waits for max ~ 5 secs. a 0xff appeares //on input-port. //If times out, it returns with 0, setting output to 0xff before. //If ok, //It sends cmd to output, then waits for max. ~ 5 seconds //till cmd is appears back on input-port. //After this operation output-port is set to 0xff //in every case. //If waiting timesout, and cmd != input-port it //returns 0, and ends. //If cmd == input-port, it waits for max. ~ 500 ms //if inport-port goes back to 0xff. //If this times out it returns 0, //otherwise 1, showing that all is going ok. //if a timeout occures, comcs_timeout is set to 1 //after this. extern int _comcs_shootup( unsigned char cmd ); //this is used by all sending routines, others //then start,end,programend. //It looks if input-port is 0xff, //If yes, it returns with 1. //If not, it waits for max ~ 1/2 sec //for this condition, (looking every 1/10 ms to //the port. //If times out, comcs_available is set, output-port //to 0xff, and function returns 0. //Otherwise nothing is done, and 1 ( ok ) is returned. extern int _comcs_porttest( void ); //Notes: //Because receiving is acting directly on type of message, and then returned, //the program can act directly to the received stuff. //So additional/following implementations can use the buffer comcs_cmd by their own. #endif