MagneticSensorChessBoard1987


Wolfgang Fahl

Front[edit]

UniChess87-0035.JPG

Back[edit]

UniChess87-0036.JPG

Connectors[edit]

UniChess87-0037.JPG UniChess87-0038.JPG UniChess87-0039.JPG

Schematics[edit]

Parts:

  1. TTL 74151 8 to 1 Multiplexer TTL74151 Pins.jpeg
  2. TTL 74154 4 to 16 Demultiplexer TTL74154 pins.png
  3. 300 Ohm Pull up Resistor

Unichess87-Schematics.JPG

Partlist[edit]

  1. chess plan 35 mm fields
  2. 64 Reed Contacts
  3. 16 Black Chess Pieces
  4. 16 White Chess Pieces
  5. 32 magnets
  6. 17 red LEDs
  7. On/Off switch
  8. Male Sub-D Connector 15
  9. Adapter cable Centronics - SUB-D 15 Female
  10. Copper Tape
  11. Aluminum Frame
  12. 1 TTL 74151
  13. 1 TTL 74154
  14. 330 Ohm Resistor
  15. Batteryholder for 3 x AA

Software[edit]

The Software was written with Borland Turbo Pascal

SCHFELD.PAS[edit]

PROGRAM Schachbrett_Ansteuerung(INPUT,OUTPUT);
TYPE
  KBrettTyp= ARRAY [0..7,0..7] OF BOOLEAN;

CONST
  BlinkTime     =   100;
  MaxBlinkTime  =  1400;
  MaxTime       =  1700;

VAR
  Pw,
  Count,LED1,LED2,
  LED3,LED4,MovCount,
  FigMovCnt: INTEGER;
  MovList                 : ARRAY[0..500] OF LSTRING(5);
  KBrett,SBrett           : KBrettTyp;
  ZugDatei                : TEXT;

(*$include: 'screen.def'*)
(*$include: 'string.def'*)

PROCEDURE ClrLED;
BEGIN
  LED1:=#80;
  LED2:=LED1;
  LED3:=LED1;
  LED4:=LED1;
END;

FUNCTION CheckBrett(D,L: INTEGER): BOOLEAN; EXTERN;
PROCEDURE Sound(Freq,Time: INTEGER); EXTERN;

FUNCTION Check(x,y: INTEGER):BOOLEAN;
VAR
  Pw,Dw,P1,P2:INTEGER;
BEGIN
  CASE  (Count MOD 2) OF
    0: BEGIN P1:=LED1; P2:=LED3; END;
    1: BEGIN P1:=LED2; P2:=LED4; END;
  END;
  IF Count<MaxBlinkTime THEN
    BEGIN
      CASE (Count DIV BlinkTime) MOD 4 OF
        0,1,2: Pw:=P1;
        3: Pw:=P2;
      END;
    END
  ELSE
    Pw:=P2;
  IF Count<MaxBlinkTime THEN
     Count:=SUCC(Count)
  ELSE
    IF Count<MaxTime THEN
      BEGIN
        IF FigMovCnt>=1 THEN
          Count:=0
        ELSE
          Count:=SUCC(Count);
      END
    ELSE
      ClrLED;
  Dw:=(x * 8) +y;
  Check:=CheckBrett(Dw,Pw);
END;

PROCEDURE State(VAR B:KBrettTyp);
VAR
  Spalte,Zeile: INTEGER;
BEGIN
  FOR Spalte:=0 TO 7 DO
    FOR Zeile:=0 TO 7 DO
      B[Spalte,Zeile]:=Check(Spalte,Zeile);
END;

PROCEDURE Kontakte;
VAR
  Spalte,Zeile: INTEGER;
BEGIN
  CLRSCR;
  ClrLED;
  REPEAT
    GOTOXY(1,1);
    FOR Spalte:=0 TO 7 DO
    BEGIN
      FOR Zeile:=0 TO 7 DO
      BEGIN
        IF KeyPressed THEN RETURN;
        IF Check(Spalte,Zeile) THEN WRITE('*') ELSE WRITE('.');
      END;
      WRITELN;
    END;
  UNTIL FALSE;
END;

PROCEDURE Scribe(VAR D:TEXT;P:INTEGER);
BEGIN
  WRITE(D,MovList[P]);
    CASE (P MOD 4) OF
      0: BEGIN WRITELN(D);WRITE(D,P DIV 4+1:3,': '); END;
      2: WRITE(D,'   ');
    OTHERWISE
    ;
    END;
END;

PROCEDURE Zuege;
  PROCEDURE Accept(X1,Y1,X2,Y2: INTEGER);
    PROCEDURE StatePos(Zeile,Spalte: INTEGER);
    BEGIN
      MovCount:=SUCC(MovCount);
      CONCAT(MovList[MovCount],CHR(ORD('A')+Zeile));
      CONCAT(MovList[MovCount],CHR(ORD('8')-Spalte));
      CASE (MovCount MOD 4) OF
       1,3: BEGIN
              IF FigMovCnt>=2 THEN
                CONCAT(MovList[MovCount],' X ')
              ELSE
                CONCAT(MovList[MovCount],' - ');
            END;
      OTHERWISE
      ;
      END;
      Scribe(OutPut,MovCount);
    END;
  BEGIN
    StatePos(X1,Y1);
    StatePos(X2,Y2);
    Count:=0;
    State(SBrett);
    Sound(800,20);
  END;

PROCEDURE ZugVerfolgen;
VAR
  AktCheck: BOOLEAN;
  P1,P2,P3,P4,Spalte,Zeile: INTEGER;

  PROCEDURE GetPos(VAR X,Y,L1,L2: INTEGER);
  BEGIN
    X:=Zeile;
    Y:=Spalte;
    L1:=(X+8) * 8;
    L2:=Y     * 8;
    Count:=0;
    State(SBrett);
  END;

BEGIN
  WRITELN('Zug-Anzeige: ');
  Scribe(OutPut,0);
  MovCount:=0;
  State(SBrett);
  FigMovCnt:=0;
  ClrLED;
  REPEAT
    FOR Zeile:=0 TO 7 DO
      FOR Spalte:=0 TO 7 DO
      BEGIN
        IF KeyPressed THEN RETURN;
        AktCheck:=Check(Spalte,Zeile);
        IF (NOT AktCheck) AND Sbrett[Spalte,Zeile] THEN
          BEGIN                { Figur Entfernt }
            IF FigMovCnt=1 THEN
              BEGIN
                GetPos(P3,P4,LED3,LED4);
                FigMovCnt:=FigMovCnt+1;
              END
            ELSE
              BEGIN
                GetPos(P1,P2,LED1,LED2);
                LED3:=LED1;
                LED4:=LED2;
                FigMovCnt:=FigMovCnt+1;
              END;
          END;
        IF AktCheck AND (NOT Sbrett[Spalte,Zeile]) THEN
          BEGIN  { Figur gesetzt }
            CASE FigMovCnt OF
              0: BEGIN
                   GetPos(P1,P2,LED1,LED2);
                 END;
              1: BEGIN
                   IF NOT ((P1=Zeile) AND (P2=Spalte)) THEN { Figur bewegt? }
                   BEGIN
                     Accept(P1,P2,Zeile,Spalte);
                     GetPos(P1,P2,LED3,LED4);
                     LED1:=LED3;LED2:=LED4;
                     FigMovCnt:=0;
                   END
                 ELSE
                   BEGIN
                     ClrLED;
                     State(SBrett);
                     FigMovCnt:=0;
                  END;
                END
            OTHERWISE
              IF (P1=Zeile) AND (P2=Spalte) THEN
                BEGIN
                  Accept(P3,P4,Zeile,Spalte);
                  GetPos(P1,P2,LED3,LED4);
                  FigMovCnt:=0;
                END
              ELSE
                BEGIN
                   Accept(P1,P2,Zeile,Spalte);
                  GetPos(P1,P2,LED3,LED4);
                  FigMovCnt:=0;
                END;
            END; { Case }
          END;
      END;
  UNTIL FALSE;
END;

VAR
   Taste: CHAR;
       z: INTEGER;
BEGIN
  CLRSCR;
  ZugVerfolgen;
  ASSIGN(ZugDatei,'SCHParti.txt');
  REWRITE(ZugDatei);
  FOR z:=0 TO MovCount DO
    Scribe(ZugDatei,z);
  CLOSE(ZugDatei);
END;

VAR
  Taste: CHAR;

BEGIN
  Window(1,1,80,25);
  REPEAT
    CLRSCR;
    WRITELN('(K)ontakt Matrix');
    WRITELN('(Z)ug-Anzeige');
    GetKey(Taste);
    MovList[0]:=NULL;
    Taste:=UpCase(Taste);
    CASE Taste OF
      'K': Kontakte;
      'Z': Zuege;
    OTHERWISE
     ;
    END;
  UNTIL Taste='E';
END.

Centronics Port Check[edit]

DATA SEGMENT PUBLIC 'DATA'

DATA ENDS
DGROUP GROUP DATA
       ASSUME CS:ADDS,DS:DGROUP,SS:DGROUP

ADDS SEGMENT 'CODE'
PUBLIC CheckBrett,Sound

Sound PROC FAR ; Freq,Time: INTEGER;
  PUSH BP
  MOV BP,SP
  PUSH DI
  MOV DI,8[BP] ; Freq;
  MOV BX,6[BP] ; Time;

  MOV AL,0B6H ; Zeitgeber Modus-Register schreiben
  OUT 43H,AL
  MOV DX,14H   ; Zeitgeber Divisor =
  MOV AX,4F38H ; 1331000/Frequenz
  DIV DI
  OUT 42H,AL   ; Zaehler in niederw. Byte Timer 2
  MOV AL,AH
  OUT 42H,AL  ; Zaehler in hoeherw. Byte Timer 2
  IN AL,61H   ; Aktuelle Einstellung Port B
  MOV AH,AL   ; In AH Sichern
  OR AL,3     ; Lautsprecher einschalten
  OUT 61H,AL

Warte:
  MOV CX,2801  ; 10 Millisekunden warten

LS_Ein:
  LOOP LS_Ein
  DEC BX       ; Einschaltzaehler auf 0?
  JNZ Warte    ; wenn nicht Lautsprecher anlassen

  MOV AL,AH    ; Port wiederherstellen
  OUT 61H,AL


  POP DI
  POP BP
  RET 4
Sound ENDP

CheckBrett PROC FAR  ;d,l: INTEGER: BOOLEAN
  PUSH BP
  MOV BP,SP
  CLI
  MOV AX,8[BP]   ; d
  MOV CX,6[BP]   ; l
  MOV DX,0278h
  OUT DX,AL      ; Port[Data]:=D
  INC DX
  IN AL,DX
  XCHG AL,CL
  DEC DX
  OUT DX,AL     ; Port[Data]:=l
  STI
  MOV AX,0
  AND CL,080h
  JNZ FALSE

  INC AX

FALSE:

  POP BP
  RET 4

CheckBrett ENDP


ADDS  ENDS
      END
1
MagneticSensorChessBoard1987 Wolfgang Fahl

SCHFELD.PAS[edit]

PROGRAM Schachbrett_Ansteuerung(INPUT,OUTPUT);
TYPE
  KBrettTyp= ARRAY [0..7,0..7] OF BOOLEAN;

CONST
  BlinkTime     =   100;
  MaxBlinkTime  =  1400;
  MaxTime       =  1700;

VAR
  Pw,
  Count,LED1,LED2,
  LED3,LED4,MovCount,
  FigMovCnt: INTEGER;
  MovList                 : ARRAY[0..500] OF LSTRING(5);
  KBrett,SBrett           : KBrettTyp;
  ZugDatei                : TEXT;

(*$include: 'screen.def'*)
(*$include: 'string.def'*)

PROCEDURE ClrLED;
BEGIN
  LED1:=#80;
  LED2:=LED1;
  LED3:=LED1;
  LED4:=LED1;
END;

FUNCTION CheckBrett(D,L: INTEGER): BOOLEAN; EXTERN;
PROCEDURE Sound(Freq,Time: INTEGER); EXTERN;

FUNCTION Check(x,y: INTEGER):BOOLEAN;
VAR
  Pw,Dw,P1,P2:INTEGER;
BEGIN
  CASE  (Count MOD 2) OF
    0: BEGIN P1:=LED1; P2:=LED3; END;
    1: BEGIN P1:=LED2; P2:=LED4; END;
  END;
  IF Count<MaxBlinkTime THEN
    BEGIN
      CASE (Count DIV BlinkTime) MOD 4 OF
        0,1,2: Pw:=P1;
        3: Pw:=P2;
      END;
    END
  ELSE
    Pw:=P2;
  IF Count<MaxBlinkTime THEN
     Count:=SUCC(Count)
  ELSE
    IF Count<MaxTime THEN
      BEGIN
        IF FigMovCnt>=1 THEN
          Count:=0
        ELSE
          Count:=SUCC(Count);
      END
    ELSE
      ClrLED;
  Dw:=(x * 8) +y;
  Check:=CheckBrett(Dw,Pw);
END;

PROCEDURE State(VAR B:KBrettTyp);
VAR
  Spalte,Zeile: INTEGER;
BEGIN
  FOR Spalte:=0 TO 7 DO
    FOR Zeile:=0 TO 7 DO
      B[Spalte,Zeile]:=Check(Spalte,Zeile);
END;

PROCEDURE Kontakte;
VAR
  Spalte,Zeile: INTEGER;
BEGIN
  CLRSCR;
  ClrLED;
  REPEAT
    GOTOXY(1,1);
    FOR Spalte:=0 TO 7 DO
    BEGIN
      FOR Zeile:=0 TO 7 DO
      BEGIN
        IF KeyPressed THEN RETURN;
        IF Check(Spalte,Zeile) THEN WRITE('*') ELSE WRITE('.');
      END;
      WRITELN;
    END;
  UNTIL FALSE;
END;

PROCEDURE Scribe(VAR D:TEXT;P:INTEGER);
BEGIN
  WRITE(D,MovList[P]);
    CASE (P MOD 4) OF
      0: BEGIN WRITELN(D);WRITE(D,P DIV 4+1:3,': '); END;
      2: WRITE(D,'   ');
    OTHERWISE
    ;
    END;
END;

PROCEDURE Zuege;
  PROCEDURE Accept(X1,Y1,X2,Y2: INTEGER);
    PROCEDURE StatePos(Zeile,Spalte: INTEGER);
    BEGIN
      MovCount:=SUCC(MovCount);
      CONCAT(MovList[MovCount],CHR(ORD('A')+Zeile));
      CONCAT(MovList[MovCount],CHR(ORD('8')-Spalte));
      CASE (MovCount MOD 4) OF
       1,3: BEGIN
              IF FigMovCnt>=2 THEN
                CONCAT(MovList[MovCount],' X ')
              ELSE
                CONCAT(MovList[MovCount],' - ');
            END;
      OTHERWISE
      ;
      END;
      Scribe(OutPut,MovCount);
    END;
  BEGIN
    StatePos(X1,Y1);
    StatePos(X2,Y2);
    Count:=0;
    State(SBrett);
    Sound(800,20);
  END;

PROCEDURE ZugVerfolgen;
VAR
  AktCheck: BOOLEAN;
  P1,P2,P3,P4,Spalte,Zeile: INTEGER;

  PROCEDURE GetPos(VAR X,Y,L1,L2: INTEGER);
  BEGIN
    X:=Zeile;
    Y:=Spalte;
    L1:=(X+8) * 8;
    L2:=Y     * 8;
    Count:=0;
    State(SBrett);
  END;

BEGIN
  WRITELN('Zug-Anzeige: ');
  Scribe(OutPut,0);
  MovCount:=0;
  State(SBrett);
  FigMovCnt:=0;
  ClrLED;
  REPEAT
    FOR Zeile:=0 TO 7 DO
      FOR Spalte:=0 TO 7 DO
      BEGIN
        IF KeyPressed THEN RETURN;
        AktCheck:=Check(Spalte,Zeile);
        IF (NOT AktCheck) AND Sbrett[Spalte,Zeile] THEN
          BEGIN                { Figur Entfernt }
            IF FigMovCnt=1 THEN
              BEGIN
                GetPos(P3,P4,LED3,LED4);
                FigMovCnt:=FigMovCnt+1;
              END
            ELSE
              BEGIN
                GetPos(P1,P2,LED1,LED2);
                LED3:=LED1;
                LED4:=LED2;
                FigMovCnt:=FigMovCnt+1;
              END;
          END;
        IF AktCheck AND (NOT Sbrett[Spalte,Zeile]) THEN
          BEGIN  { Figur gesetzt }
            CASE FigMovCnt OF
              0: BEGIN
                   GetPos(P1,P2,LED1,LED2);
                 END;
              1: BEGIN
                   IF NOT ((P1=Zeile) AND (P2=Spalte)) THEN { Figur bewegt? }
                   BEGIN
                     Accept(P1,P2,Zeile,Spalte);
                     GetPos(P1,P2,LED3,LED4);
                     LED1:=LED3;LED2:=LED4;
                     FigMovCnt:=0;
                   END
                 ELSE
                   BEGIN
                     ClrLED;
                     State(SBrett);
                     FigMovCnt:=0;
                  END;
                END
            OTHERWISE
              IF (P1=Zeile) AND (P2=Spalte) THEN
                BEGIN
                  Accept(P3,P4,Zeile,Spalte);
                  GetPos(P1,P2,LED3,LED4);
                  FigMovCnt:=0;
                END
              ELSE
                BEGIN
                   Accept(P1,P2,Zeile,Spalte);
                  GetPos(P1,P2,LED3,LED4);
                  FigMovCnt:=0;
                END;
            END; { Case }
          END;
      END;
  UNTIL FALSE;
END;

VAR
   Taste: CHAR;
       z: INTEGER;
BEGIN
  CLRSCR;
  ZugVerfolgen;
  ASSIGN(ZugDatei,'SCHParti.txt');
  REWRITE(ZugDatei);
  FOR z:=0 TO MovCount DO
    Scribe(ZugDatei,z);
  CLOSE(ZugDatei);
END;

VAR
  Taste: CHAR;

BEGIN
  Window(1,1,80,25);
  REPEAT
    CLRSCR;
    WRITELN('(K)ontakt Matrix');
    WRITELN('(Z)ug-Anzeige');
    GetKey(Taste);
    MovList[0]:=NULL;
    Taste:=UpCase(Taste);
    CASE Taste OF
      'K': Kontakte;
      'Z': Zuege;
    OTHERWISE
     ;
    END;
  UNTIL Taste='E';
END.

Centronics Port Check[edit]

DATA SEGMENT PUBLIC 'DATA'

DATA ENDS
DGROUP GROUP DATA
       ASSUME CS:ADDS,DS:DGROUP,SS:DGROUP

ADDS SEGMENT 'CODE'
PUBLIC CheckBrett,Sound

Sound PROC FAR ; Freq,Time: INTEGER;
  PUSH BP
  MOV BP,SP
  PUSH DI
  MOV DI,8[BP] ; Freq;
  MOV BX,6[BP] ; Time;

  MOV AL,0B6H ; Zeitgeber Modus-Register schreiben
  OUT 43H,AL
  MOV DX,14H   ; Zeitgeber Divisor =
  MOV AX,4F38H ; 1331000/Frequenz
  DIV DI
  OUT 42H,AL   ; Zaehler in niederw. Byte Timer 2
  MOV AL,AH
  OUT 42H,AL  ; Zaehler in hoeherw. Byte Timer 2
  IN AL,61H   ; Aktuelle Einstellung Port B
  MOV AH,AL   ; In AH Sichern
  OR AL,3     ; Lautsprecher einschalten
  OUT 61H,AL

Warte:
  MOV CX,2801  ; 10 Millisekunden warten

LS_Ein:
  LOOP LS_Ein
  DEC BX       ; Einschaltzaehler auf 0?
  JNZ Warte    ; wenn nicht Lautsprecher anlassen

  MOV AL,AH    ; Port wiederherstellen
  OUT 61H,AL


  POP DI
  POP BP
  RET 4
Sound ENDP

CheckBrett PROC FAR  ;d,l: INTEGER: BOOLEAN
  PUSH BP
  MOV BP,SP
  CLI
  MOV AX,8[BP]   ; d
  MOV CX,6[BP]   ; l
  MOV DX,0278h
  OUT DX,AL      ; Port[Data]:=D
  INC DX
  IN AL,DX
  XCHG AL,CL
  DEC DX
  OUT DX,AL     ; Port[Data]:=l
  STI
  MOV AX,0
  AND CL,080h
  JNZ FALSE

  INC AX

FALSE:

  POP BP
  RET 4

CheckBrett ENDP


ADDS  ENDS
      END
🖨 🚪