int ChannelInputAGS (ags_t * State) { // // This will need to accept data from the NASSP code and pass it through to Virtual // AGS. // #if 0 static int SocketInterlace = 0; int i, j, k; unsigned char c; Client_t *Client; int Mask; //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, &c, 1, 0); if (k == 0 || k == -1) break; Client->Packet[Client->Size++] = c; } // Process a received packet. if (Client->Size >= 4) { int 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 (!ParseIoPacketAGS (Client->Packet, &Type, &Data)) switch (Type) { case 000: // PGNS theta integrator. case 001: // PGNS phi integrator. case 002: // PGNS psi integrator. j = IO_2001 + Type; if (Data == 0) State->InputPorts[j] = 0; else { State->InputPorts[j] += SignExtendAGS (Data) * 4; State->InputPorts[j] &= 0377774; } break; case 005: // discrete input word 2. // If the READ OUT or ENTR keys are active, // we must intercept them and buffer the // associated data before letting the CPU // know about it. k = ((Data & 0777) << 9); j = (Data & k) | ~k; if (0 == (j & 04000)) // ENTR? { DedaBufferCount = 0; // Prepare to collect data. DedaBufferWanted = 9; Data |= 04000; // Reset the ENTR key. // Request DEDA shift data. ChannelOutputAGS (040, State->OutputPorts[IO_ODISCRETES] & ~010); } else if (0 == (j & 02000)) // READ OUT? { DedaBufferCount = 0; // Prepare to collect data. DedaBufferWanted = 3; Data |= 02000; // Reset the READ OUT key. // Request DEDA shift data. ChannelOutputAGS (040, State->OutputPorts[IO_ODISCRETES] & ~010); } // Yes, it is supposed to fall through here. case 004: // Discrete input word 1. j = IO_2020 + (Type - 4); Mask = ((Data & 0777) << 9); State->InputPorts[j] &= ~Mask; State->InputPorts[j] |= (Data & Mask); break; case 007: // DEDA. // If we are buffering this input, we have to intercept it. if (DedaBufferWanted) { if (DedaBufferCount < DedaBufferWanted) { DedaBuffer[DedaBufferCount++] = (Data & 0360000); if (DedaBufferCount < DedaBufferWanted) { // Request more DEDA shift data. ChannelOutputAGS (040, State->OutputPorts[IO_ODISCRETES] & ~010); } else { // The data is all buffered. We can tell the // CPU that the ENTR or READ OUT key was pressed. //printf ("Buffered from DEDA: CLR"); //for (j = 0; j < DedaBufferWanted; j++) // printf (" %02o", DedaBuffer[j] >> 13); DedaBufferReadout = -1; if (DedaBufferWanted == 3) { State->InputPorts[IO_2040] &= ~02000; // READ OUT //printf (" READOUT\n"); } else { State->InputPorts[IO_2040] &= ~04000; // ENTR. //printf (" ENTR\n"); } } } } break; case 011: // delta-integral-q counter case 012: // delta-integral-r counter case 013: // delta-integral-p counter j = IO_6002 + (Type - 011); State->InputPorts[j] += SignExtendAGS (Data) * 0100; State->InputPorts[j] &= 0377700; break; case 014: // delta-Vx counter. case 015: // delta-Vy counter. case 016: // delta-Vz counter. j = IO_6020 + (Type - 014); State->InputPorts[j] += SignExtendAGS (Data) * 0100; State->InputPorts[j] &= 0377700; break; case 017: // downlink telemetry State->InputPorts[IO_6200] = Data; // Make the Downlink Telemetry Stop bit active. State->InputPorts[IO_2020] &= ~0200000; break; } Client->Size = 0; } } } #endif return (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; }