Example #1
0
void
TimerClass::ActOnIncomingIO(unsigned char *Packet)
{
  static uint16_t lastReceived[16] =
    { 0 }, lastOUT1 = 0;
  static uint8_t signs[3] =
    { 0 };
  int Channel, Value, uBit, i;
  // Check to see if the message has a yaAGC signature.  If not,
  // ignore it.  The yaAGC signature is 00 01 10 11 in the
  // 2 most-significant bits of the packet's bytes.  We are
  // guaranteed that the first byte is signed 00, so we don't
  // need to check it.
  if (0x40 != (Packet[1] & 0xc0) || 0x80 != (Packet[2] & 0xc0)
      || 0xc0 != (Packet[3] & 0xc0))
    {
      printf("yaDSKYb1:  illegal packet: %02X %02X %02X %02X\n", Packet[0],
          Packet[1], Packet[2], Packet[3]);
      goto Error;
    }
  if (ParseIoPacket(Packet, &Channel, &Value, &uBit))
    {
      printf("yaDSKYb1:  illegal values: %02X %02X %02X %02X\n", Packet[0],
          Packet[1], Packet[2], Packet[3]);
      goto Error;
    }
  //printf("yaDSKYb1:  received channel=%02o value=%04o ubit=%o\n", Channel,
  //    Value, uBit);
#if 0
  // The following is just a temporary thing I'm using to debug telemetry,
  // and really has nothing to do with the DSKY, and so won't appear in the
  // final program.
  if (Channel == 014)
    {
      static FILE *log = NULL;
      if (log == NULL)
        log = fopen("temp.log", "w");
      if (log != NULL)
        {
          int wordOrder = 1 & (lastOUT1 >> 8);
          // Interpret the data as described on p. 53 of Compleat Sunrise.
          // Note that the actual data does not seem to correspond in any
          // way to that description.
          if (wordOrder)
            fprintf(log, "Data word: %05o\n", Value & 077777);
          else if (00000 == (Value & 076000))
            fprintf(log, "ID word: %04o\n", Value & 01777);
          else if (02000 == (Value & 076000))
            fprintf(log, "Input character word: %s %s KEYCODE=%02o\n",
                (Value & 0100) ? "MARK" : "KEY",
                (Value & 040) ? "UPLINK" : "KBD", (Value & 037));
          else
            fprintf(log, "Relay word: relay=%02o settings=%04o\n",
                017 & (Value >> 11), (Value & 03777));
          fflush(log);
        }
    }
Example #2
0
int
ChannelInput (agc_t *State)
{
  static int SocketInterlace = 0;
  int i, j, k;
  unsigned char c;
  Client_t *Client;
  int Channel, Value;

  //We use SocketInterlace to slow down the number
  // of polls of the sockets.
  if (SocketInterlace > 0)
    SocketInterlace--;
  else
    {
      SocketInterlace = SocketInterlaceReload;
      for (i = 0, Client = Clients; i < MAX_CLIENTS; i++, Client++)
	if (Client->Socket != -1)
	  {
	    // We arbitrarily adopt the rule that we'll process at most one
	    // packet per client per instruction cycle.
	    for (j = Client->Size; j < 4; j++)
	      {
		k = recv (Client->Socket, (char *) &c, 1, 0);
		if (k == 0 || k == -1)
		  break;
		// 20090318 RSB.  Added this filter for a little robustness,
		// but it shouldn't be needed.
		if (!(
		      (Signatures[j] == (c & 0xC0)) ||
		      (DebugDeda && (SignaturesAgs[j] == (c & 0xC0)))
		    )
		   )
		  {
		    Client->Size = 0;
		    if (0 != (c & 0xC0))
		      {
		        j = -1;
	                continue;
		      }
		    j = 0;
		  }
		Client->Packet[Client->Size++] = c;
	      }
	    // Process a received packet.
	    if (Client->Size >= 4)
	      {
		int uBit, Type, Data;
		//printf ("Received from %d: %02X %02X %02X %02X\n",
		//	i, Client->Packet[0], Client->Packet[1],
		//	Client->Packet[2], Client->Packet[3]);
		if (!ParseIoPacket (Client->Packet, &Channel, &Value, &uBit))
		  {
		    // Convert to AGC format (upper 15 bits).
		    Value &= 077777;
		    if (uBit)
		      {
			Client->ChannelMasks[Channel] = Value;
		      }
		    else if (Channel & 0x80)
		      {
		        // In this case we're dealing with a counter increment.
			// So increment the counter.
			//printf ("Channel=%02o Int=%o\n", Channel, Value);
			UnprogrammedIncrement (State, Channel, Value);
			Client->Size = 0;
			return (1);
		      }
		    else
		      {
			Value &= Client->ChannelMasks[Channel];
			Value |=
			  ReadIO (State,
				  Channel) & ~Client->ChannelMasks[Channel];
			WriteIO (State, Channel, Value);
			// If this is a keystroke from the DSKY, generate an interrupt req.
			if (Channel == 015)
			  State->InterruptRequests[5] = 1;
			// If this is on fictitious input channel 0173, then the data
			// should be placed in the INLINK counter register, and an
			// UPRUPT interrupt request should be set.
			else if (Channel == 0173)
			  {
			    State->Erasable[0][RegINLINK] = (Value & 077777);
			    State->InterruptRequests[7] = 1;
			  }
			// Fictitious registers for rotational hand controller (RHC).
			// Note that the RHC angles are not immediately used, but
			// merely squirreled away for later.  They won't actually
			// go into the counter registers until the RHC counters are
			// enabled and the data requested (bits 8,9 of channel 13).
			else if (Channel == 0166)
			  {
			    LastRhcPitch = Value;
			    ChannelOutput (State, Channel, Value);	// echo
			  }
			else if (Channel == 0167)
			  {
			    LastRhcYaw = Value;
			    ChannelOutput (State, Channel, Value);	// echo
			  }
			else if (Channel == 0170)
			  {
			    LastRhcRoll = Value;
			    ChannelOutput (State, Channel, Value);	// echo
			  }
			else if (Channel == 031)
			  {
			    static int LastInDetent = 040000;
			    int InDetent;
			    ChannelOutput (State, Channel, Value);
			    // If the RHC stick has moved out of detent,
			    // generate a RUPT10 interrupt.
			    InDetent = (040000 & Value);
			    if (LastInDetent && !InDetent)
			      State->InterruptRequests[10] = 1;
			    LastInDetent = InDetent;
			  }
			//---------------------------------------------------------------
			// For --debug-dsky mode.
			if (DebugDsky)
			  {
			    if (Channel == 032)
			      {
				// For DebugDsky purposes only, the PRO key is translated
				// to appear as the otherwise-fictitious KeyCode 0.
				if (0 != (Value & 020000))
				  {
				    Channel = 015;
				    Value = 0;
				  }
			      }
			    if (Channel == 015)
			      {
				int i, CurrentValue;
				Value &= 077777;
				for (i = 0; i < NumDebugRules; i++)
				  if (Value == DebugRules[i].KeyCode)
				    {
				      CurrentValue =
					CurrentChannelValues[DebugRules[i].
							     Channel];
				      switch (DebugRules[i].Logic)
					{
					case '=':
					  CurrentValue = DebugRules[i].Value;
					  break;
					case '|':
					  CurrentValue |= DebugRules[i].Value;
					  break;
					case '&':
					  CurrentValue &= DebugRules[i].Value;
					  break;
					case '^':
					  CurrentValue ^= DebugRules[i].Value;
					  break;
					default:
					  break;
					}
				      CurrentChannelValues[DebugRules[i].
							   Channel] =
					CurrentValue;
				      ChannelOutput (State,
						     DebugRules[i].Channel,
						     CurrentValue);
				    }
			      }
			    //if (Channel != 032 && Channel != 015)
			    //  WriteIO (State, Channel, Value);
			  }
			//---------------------------------------------------------------
		      }
		  }
		else if (DebugDeda && !ParseIoPacketAGS (Client->Packet, &Type, &Data))
		  {
		    // The following code is present only for debugging yaDEDA
		    // communications, and has no interesting purpose yaAGC-wise.
		    static unsigned char Buffer[9];
		    static int NumInBuffer = 0, NumWanted = 0, Collecting = 0;
		    static unsigned char Packet[4];
		    if (Type == 05 && (Data == 0777002 || Data == 0777004 ||
		        Data == 0777010 || Data == 0777020))
		      printf ("DEDA key release.\n");
		    else if (Collecting && Type == 07)
		      {
		        Buffer[NumInBuffer++] = Data >> 13;
			if (NumInBuffer < NumWanted)
			  send (Client->Socket, (const char *) Packet, 4, 0);
			else
			  {
			    int i;
			    Collecting = 0;
			    printf ("Received %d DEDA nibbles:", NumWanted);
			    for (i = 0; i < NumWanted; i++)
			      printf (" %1X", Buffer[i]);
			    printf ("\n");
			    if (NumWanted == 3)
			      {
			        if (!DedaQuiet)
			          DedaMonitor = 1;
				DedaAddress = Buffer[0] * 0100 + Buffer[1] * 010 + Buffer[2];
				DedaWhen = State->CycleCounter;
			      }
			  }
		      }
		    else if (Type == 05 && (Data == 0775002 || Data == 0773004))
		      {
		        NumInBuffer = 0;
			Collecting = 1;
			if (Data == 0775002)
			  {
		            printf ("Received DEDA READOUT.\n");
			    NumWanted = 3;
			  }
			else
			  {
		            printf ("Received DEDA ENTR.\n");
			    NumWanted = 9;
			  }
			FormIoPacketAGS (040, ~010, Packet);
			send (Client->Socket, (const char *) Packet, 4, 0);
		      }
		    else if (Type == 05 && Data == 0767010)
		      {
		        printf ("Received DEDA HOLD.\n");
			DedaMonitor = 0;
		      }
		    else if (Type == 05 && Data == 0757020)
		      {
		        printf ("Received DEDA CLR.\n");
			DedaMonitor = 0;
		      }
		    else
		      printf ("Unknown AGS packet %02X %02X %02X %02X\n",
		              Client->Packet[0], Client->Packet[1],
			      Client->Packet[2], Client->Packet[3]);
		  }
		Client->Size = 0;
	      }
Example #3
0
int
ChannelInput(agcBlock1_t *State)
{
  static int SocketInterlace = 0;
  int i, j, k;
  unsigned char c;
  Client_t *Client;
  int Channel, Value;

  //We use SocketInterlace to slow down the number
  // of polls of the sockets.
  if (SocketInterlace > 0)
    SocketInterlace--;
  else
    {
      SocketInterlace = SocketInterlaceReload;
      for (i = 0, Client = Clients; i < MAX_CLIENTS; i++, Client++)
        if (Client->Socket != -1)
          {
            // We arbitrarily adopt the rule that we'll process at most one
            // packet per client per instruction cycle.
            for (j = Client->Size; j < 4; j++)
              {
                k = recv(Client->Socket, (char *) &c, 1, 0);
                if (k == 0 || k == -1)
                  break;
                // 20090318 RSB.  Added this filter for a little robustness,
                // but it shouldn't be needed.
                if (Signatures[j] != (c & 0xC0))
                  {
                    Client->Size = 0;
                    if (0 != (c & 0xC0))
                      {
                        j = -1;
                        continue;
                      }
                    j = 0;
                  }
                Client->Packet[Client->Size++] = c;
              }
            // Process a received packet.
            if (Client->Size >= 4)
              {
                int uBit, Type, Data;
                //printf ("Received from %d: %02X %02X %02X %02X\n",
                //	i, Client->Packet[0], Client->Packet[1],
                //	Client->Packet[2], Client->Packet[3]);
                if (!ParseIoPacket(Client->Packet, &Channel, &Value, &uBit))
                  {
                    // Convert to AGC format (upper 15 bits).
                    Value &= 077777;
                    if (uBit)
                      {
                        Client->ChannelMasks[Channel] = Value;
                      }
                    else if (Channel & 0x80)
                      {
                        // In this case we're dealing with a counter increment.
                        // So increment the counter.
                        //printf ("Channel=%02o Int=%o\n", Channel, Value);
                        // FIXME
                        //UnprogrammedIncrement(State, Channel, Value);
                        Client->Size = 0;
                        return (1);
                      }
                    else
                      {
                        Value &= Client->ChannelMasks[Channel];
                        Value |= State->memory[Channel]
                            & ~Client->ChannelMasks[Channel];
                        State->memory[Channel] = Value;
                        // If this is a keystroke from the DSKY, generate an interrupt req.
                        //---------------------------------------------------------------
                      }
                  }
                Client->Size = 0;
              }
          }
    }
  return (0);
}