Turbo51 Files

boolean byte code data dptr file function high idata lcall memory module procedure record register segment type value xdata 8051
General Files

Turbo51 Files

Turbo51 supports files - a general framework for IO handling. However, you have to provide the low level IO procedures. Files can be untyped, typed (File of SomeType) and of type Text (ASCII text terminated with line feed #10 character). The following procedures support files:

- Assign
- Read
- ReadLn
- Write
- WriteLn
- BlockRead
- BlockWrite

Here is a simple example of calculator using files:

    Program Files;

    // Should work on any 8051 microcontroller

    Const
     Oscillator = 22118400;
     BaudRate   = 19200;
     BaudRateTimerValue = Byte (- Oscillator div 12 div 32 div BaudRate);

    Var SerialPort: Text;
        Num1, Num2: LongInt;

    Procedure WriteToSerialPort; Assembler;
    Asm
      CLR   TI
      MOV   SBUF, A
    @WaitLoop:
      JNB   TI, @WaitLoop
    end;

    Function ReadFromSerialPort: Char;
    Var ByteResult: Byte absolute Result;
    begin
      While not RI do;
      RI := False;
      ByteResult := SBUF;

    { Echo character }

      Asm
        MOV    A, Result
        LCALL  WriteToSerialPort
      end;
    end;

    Procedure Init;
    begin
      TL1  := BaudRateTimerValue;
      TH1  := BaudRateTimerValue;
      TMOD := %00100001;    { Timer1: no GATE, 8 bit timer, autoreload }
      SCON := %01010000;    { Serial Mode 1, Enable Reception }
      TI   := True;         { Indicate TX ready }
      TR1  := True;         { Enable timer 1 }
    end;

    begin
      Init;
      Assign (SerialPort, ReadFromSerialPort, WriteToSerialPort);

      Writeln (SerialPort, 'Turbo51 IO file demo');
      Repeat
        Write   (SerialPort, 'Enter first number: ');
        Readln  (SerialPort, Num1);
        Write   (SerialPort, 'Enter second number: ');
        Readln  (SerialPort, Num2);
        Writeln (SerialPort, Num1, ' + ', Num2, ' = ', Num1 + Num2);
      until False;
    end.

This example compiled looks like this:

    $REGISTERBANK (0)

    _CODE         SEGMENT  CODE
    _CONST        SEGMENT  CODE
    _DATA         SEGMENT  DATA

                  EXTRN    DATA  (StackStart)
                  EXTRN    DATA  (CurrentIO)

                  EXTRN    CODE  (sysWriteStr_CODE)
                  EXTRN    CODE  (sysWriteLine)
                  EXTRN    CODE  (sysReadLongInt)
                  EXTRN    CODE  (sysStore_Long0_To_IDATA)
                  EXTRN    CODE  (sysReadLine)
                  EXTRN    CODE  (sysLoad_Long0_From_IDATA)
                  EXTRN    CODE  (sysPushLongIntBCD)
                  EXTRN    CODE  (sysWriteDecimalPushedBytes)
                  EXTRN    CODE  (sysLoad_Long1_From_IDATA)
                  EXTRN    CODE  (sysLongAddition)

    ; Program Files;
    ;
    ; // Should work on any 8051 microcontroller
    ;
    ; Const

    RSEG _CONST

    ;  Oscillator = 22118400;
    ;  BaudRate   = 19200;
    ;  BaudRateTimerValue = Byte (- Oscillator div 12 div 32 div BaudRate);
    ;
    ; Var SerialPort: Text;

    RSEG _DATA

    SerialPort:                     DS       4

    ;     Num1, Num2: LongInt;
    Num1:                           DS       4
    Num2:                           DS       4

    ;
    ; Procedure WriteToSerialPort; Assembler;

    RSEG _CODE

    USING 0

    WriteToSerialPort:
    ; Asm
    ;   CLR   TI
                  CLR       SCON.1

    ;   MOV   SBUF, A
                  MOV       SBUF, A

    ; @WaitLoop:

    ;   JNB   TI, @WaitLoop
    L_00B0:
                  JNB       SCON.1, L_00B0

    ; end;
                  RET

    ;
    ; Function ReadFromSerialPort: Char;

    RSEG _DATA

    ReadFromSerialPort_Result:      DS       1

    ; Var ByteResult: Byte absolute Result;
    ByteResult                      EQU      ReadFromSerialPort_Result

    RSEG _CODE

    ReadFromSerialPort:
    ; begin
    ;   While not RI do;
    L_00B4:
                  JNB       SCON.0, L_00B4

    ;   RI := False;
                  CLR       SCON.0

    ;   ByteResult := SBUF;
                  MOV       ReadFromSerialPort_Result, SBUF

    ;
    ; { Echo character }
    ;
    ;   Asm
    ;     MOV    A, Result
                  MOV       A, ReadFromSerialPort_Result

    ;     LCALL  WriteToSerialPort
                  LCALL     WriteToSerialPort

    ;   end;
    ; end;
                  MOV       A, ReadFromSerialPort_Result
                  RET

    ;
    ;
    ; Procedure Init;

    Init:
    ; begin
    ;   TL1  := BaudRateTimerValue;
                  MOV       TL1, #$FD

    ;   TH1  := BaudRateTimerValue;
                  MOV       TH1, #$FD

    ;   TMOD := %00100001;    { Timer1: no GATE, 8 bit timer, autoreload }
                  MOV       TMOD, #$21

    ;   SCON := %01010000;    { Serial Mode 1, Enable Reception }
                  MOV       SCON, #$50

    ;   TI   := True;         { Indicate TX ready }
                  SETB      SCON.1

    ;   TR1  := True;         { Enable timer 1 }
                  SETB      TCON.6

    ; end;
                  RET

    ;

    RSEG _CONST

    C_0354:                         DB        20, 'Turbo51 IO file demo'
    C_0369:                         DB        20, 'Enter first number: '
    C_037E:                         DB        21, 'Enter second number: '
    C_0394:                         DB        3, ' + '
    C_0398:                         DB        3, ' = '

    CSEG AT 0

    PROGRAM:
    ; begin
                  MOV       SP, #StackStart-1

    ;   Init;
                  LCALL     Init

    ;   Assign (SerialPort, ReadFromSerialPort, WriteToSerialPort);
                  MOV       SerialPort, #LOW  (WriteToSerialPort)
                  MOV       SerialPort+1, #HIGH (WriteToSerialPort)
                  MOV       SerialPort+2, #LOW  (ReadFromSerialPort)
                  MOV       SerialPort+3, #HIGH (ReadFromSerialPort)

    ;
    ;   Writeln (SerialPort, 'Turbo51 IO file demo');
                  MOV       CurrentIO, SerialPort
                  MOV       CurrentIO+1, SerialPort+1
                  MOV       DPTR, #C_0354
                  MOV       R6, #0
                  LCALL     sysWriteStr_CODE
                  LCALL     sysWriteLine

    ;   Repeat

    ;     Write   (SerialPort, 'Enter first number: ');
    L_0023:
                  MOV       CurrentIO, SerialPort
                  MOV       CurrentIO+1, SerialPort+1
                  MOV       DPTR, #C_0369
                  MOV       R6, #0
                  LCALL     sysWriteStr_CODE

    ;     Readln  (SerialPort, Num1);
                  MOV       CurrentIO+2, SerialPort+2
                  MOV       CurrentIO+3, SerialPort+3
                  LCALL     sysReadLongInt
                  MOV       R0, #Num1
                  LCALL     sysStore_Long0_To_IDATA
                  LCALL     sysReadLine

    ;     Write   (SerialPort, 'Enter second number: ');
                  MOV       CurrentIO, SerialPort
                  MOV       CurrentIO+1, SerialPort+1
                  MOV       DPTR, #C_037E
                  MOV       R6, #0
                  LCALL     sysWriteStr_CODE

    ;     Readln  (SerialPort, Num2);
                  MOV       CurrentIO+2, SerialPort+2
                  MOV       CurrentIO+3, SerialPort+3
                  LCALL     sysReadLongInt
                  MOV       R0, #Num2
                  LCALL     sysStore_Long0_To_IDATA
                  LCALL     sysReadLine

    ;     Writeln (SerialPort, Num1, ' + ', Num2, ' = ', Num1 + Num2);
                  MOV       CurrentIO, SerialPort
                  MOV       CurrentIO+1, SerialPort+1
                  MOV       R0, #Num1
                  LCALL     sysLoad_Long0_From_IDATA
                  LCALL     sysPushLongIntBCD
                  MOV       R6, #0
                  LCALL     sysWriteDecimalPushedBytes
                  MOV       DPTR, #C_0394
                  MOV       R6, #0
                  LCALL     sysWriteStr_CODE
                  MOV       R0, #Num2
                  LCALL     sysLoad_Long0_From_IDATA
                  LCALL     sysPushLongIntBCD
                  MOV       R6, #0
                  LCALL     sysWriteDecimalPushedBytes
                  MOV       DPTR, #C_0398
                  MOV       R6, #0
                  LCALL     sysWriteStr_CODE
                  MOV       R0, #Num1
                  LCALL     sysLoad_Long0_From_IDATA
                  MOV       R0, #Num2
                  LCALL     sysLoad_Long1_From_IDATA
                  LCALL     sysLongAddition
                  LCALL     sysPushLongIntBCD
                  MOV       R6, #0
                  LCALL     sysWriteDecimalPushedBytes
                  LCALL     sysWriteLine

    ;   until False;
                  LJMP      L_0023

    ; end.
    ;
                  END

With the Assign statement you assign ReadFromSerialPort and WriteToSerialPort procedures to the File variable SerialPort. Check system procedure Assign for Read and Write procedure special rquirements. Turbo51 before each call to read/write procedure assigns file's read/write procedure to the CurrentIO system variable of type File. CurrentIO file is used by all system procedures which read from or write to actual device. System unit defines another file varable of type Text, SystemIO with aliases Input and Output. This text file is used for Read/ReadLn and Write/WriteLn procedures when no text file is specified. Before SystemIO can be used actual read/write procedures must be be assigend to it.

If there are a lot of read/write calls and we have only one IO device then we can avoid specifying this file and loading of CurrentIO file variable each time we call read/write with the compiler directve DefaultFile set to On (default is Off). Of course, we have to assign our procedures to the CurrentIO file variable with the Assign procedure. Be careful with this directive: any call to read/write with specified file variable (i.e. in other units compiled with DefaultFile set to Off) will overwrite CurrentIO variable. In such case the CurrentIO has to be assigned again. With this directive set to On the previous example would look like this:

    PROGRAM:
    ; {$DefaultFile On }
    ;
    ; begin
                  MOV       SP, #StackStart-1

    ;   Init;
                  LCALL     Init

    ;   Assign (CurrentIO, ReadFromSerialPort, WriteToSerialPort);
                  MOV       CurrentIO, #LOW  (WriteToSerialPort)
                  MOV       CurrentIO+1, #HIGH (WriteToSerialPort)
                  MOV       CurrentIO+2, #LOW  (ReadFromSerialPort)
                  MOV       CurrentIO+3, #HIGH (ReadFromSerialPort)

    ;
    ;   Writeln ('Turbo51 IO file demo');
                  MOV       DPTR, #C_032F
                  MOV       R6, #0
                  LCALL     sysWriteStr_CODE
                  LCALL     sysWriteLine

    ;   Repeat

    ;     Write   ('Enter first number: ');
    L_001D:
                  MOV       DPTR, #C_0344
                  MOV       R6, #0
                  LCALL     sysWriteStr_CODE

    ;     Readln  (Num1);
                  LCALL     sysReadLongInt
                  MOV       R0, #Num1
                  LCALL     sysStore_Long0_To_IDATA
                  LCALL     sysReadLine

    ;     Write   ('Enter second number: ');
                  MOV       DPTR, #C_0359
                  MOV       R6, #0
                  LCALL     sysWriteStr_CODE

    ;     Readln  (Num2);
                  LCALL     sysReadLongInt
                  MOV       R0, #Num2
                  LCALL     sysStore_Long0_To_IDATA
                  LCALL     sysReadLine

    ;     Writeln (Num1, ' + ', Num2, ' = ', Num1 + Num2);
                  MOV       R0, #Num1
                  LCALL     sysLoad_Long0_From_IDATA
                  LCALL     sysPushLongIntBCD
                  MOV       R6, #0
                  LCALL     sysWriteDecimalPushedBytes
                  MOV       DPTR, #C_036F
                  MOV       R6, #0
                  LCALL     sysWriteStr_CODE
                  MOV       R0, #Num2
                  LCALL     sysLoad_Long0_From_IDATA
                  LCALL     sysPushLongIntBCD
                  MOV       R6, #0
                  LCALL     sysWriteDecimalPushedBytes
                  MOV       DPTR, #C_0373
                  MOV       R6, #0
                  LCALL     sysWriteStr_CODE
                  MOV       R0, #Num1
                  LCALL     sysLoad_Long0_From_IDATA
                  MOV       R0, #Num2
                  LCALL     sysLoad_Long1_From_IDATA
                  LCALL     sysLongAddition
                  LCALL     sysPushLongIntBCD
                  MOV       R6, #0
                  LCALL     sysWriteDecimalPushedBytes
                  LCALL     sysWriteLine

    ;   until False;
                  SJMP      L_001D

    ; end.
    ;
                  END