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); } }
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; }
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); }