ICL 1900 Character sets

The 1900 is a six bit character machine, using a 64 character set.

For paper tape and communications a seven bit character set is used, derived from an early version of ASCII, described as the ECMA (European Computer Manufacturers Association) character set in ICL documentation.

For conversion between the internal 6 bit code and ECMA codes a shift system is used. Three 6 bit codes were used as α (alpha), β (beta) and δ (delta) shifts. When a α shift is output all subsequent six bit characters would be output in upper case. When a β shift is output then subsequent six bit characters would be converted to their lower case equivalents. When a δ shift is output then the next character would be a control character.

The exact mapping is:
octal
code
6 bit α β δ
#00000DLE (TC7)
#01111 (DC1)
#02222 (DC2)
#03333 (DC3)
#04444 (DC4)
#05555NAK (TC8)
#06666SYN (TC9)
#07777ETB (TC10)
#10888CAN
#11999EM
#12:::SUB
#13;;;ESC
#14<<<FS (IS1)
#15===GS (IS2)
#16>>>RS (IS3)
#17???US (IS4)
#20SPSPSPNUL (TC0)
#21!!!SOH (TC1)
#22"""STX (TC2)
#23###ETX (TC3)
#24£££EOT (TC4)
#25%%%ENQ (TC5)
#26&&&ACK (TC6)
#27'''BEL
#30(((BS (FE0)
#31)))HT (FE1)
#32***NL (FE2)
#33+++LF (FE2)
#34,,,FF (FE3)
#35---CR (FE4)
#36...SO
#37///SI
#40@@_
#41AAa
#42BBb
#43CCc
#44DDd
#45EEe
#46FFf
#47GGg
#50HHh
#51IIi
#52JJj
#53KKk
#54LLl
#55MMm
#56NNn
#57OOo
#60PPp
#61QQq
#62RRr
#63SSs
#64TTt$
#65UUu]
#66VVv
#67WWw
#70XXx|
#71YYy}
#72ZZz~
#73[[{DEL
#74$ALPHAALPHA
#75]BETABETA
#76DELTADELTA
#77FILLFILL

For example, the string "You want $200, are you MAD" would be coded as:

$Y]OU WANT ^T200, ARE YOU $MAD

Where $ is an α shift, ] is a β shift and ^ is a δ shift.

The text "WARNING", CR, LF, BEL would be output by:

$WARNING^-^*^'

Note the following differences between the ICL ECMA character set and ASCII:

7 bit
code
ECMA ASCII
#012NLLF
#013LFVT
#044£$
#134$\
#136^
#137_
#140_`

The NL/LF difference is largely notational, to output a carriage return, linefeed to a terminal the system outputs the ECMA sequence "CR", "NL".

(On some output devices the uparrow and leftarrow were displayed as the newfangled ASCII caret and underline, on some the underline is displayed as the backquote).

Note that the ICL/ECMA character set has no backslash.

In order to allow localisation the "{", "|", "}" and "~" characters could be replaced by national variants, for example "é", "ç", "è" and "à" in France.

Algorithmic conversion between ICL 6 bit code and ICL/ECMA 7 bit code

Although it is possible to convert between the 6 bit (shifted or unshifted) character set and the 7 bit ECMA character set using lookup tables it is also quite easy to do an algorithmic conversion, for example:

ECMA to ICL 6 bit

Take the top two bits of the 7 bit character as the "zone"*, then:
      Zone 0:          // control characters
          0x00 .. 0x0f (#000 .. #017, NUL .. SI)
             => DELTA, #20 .. #37
          0x10 .. 0x1f (#020 .. #037, DLE .. US)
             => DELTA, #00 .. #17
          So 6bit = DELTA, 7bit XOR #20

      Zone 1:          // characters same in ALPHA and BETA
          0x20 .. 0x2f (#040 .. #057, " " .. "/")
             => #20 .. #37
          0x30 .. 0x3f (#060 .. #077, "0" .. "?")
             => #00 .. #17
          so 6bit = 7bit XOR #60

      Zone 2:          // ALPHA shift characters
          0x40 .. 0x5b (#100 .. #133, "@" .. "[" )
             => ALPHA, #40 .. #73
             so 6bit = ALPHA, (7bit OR #40) AND #77
          0x5c .. 0x5f (#134 .. #137, "$" .. "<-")
             => DELTA, #64 .. #67
             so 6bit = DELTA, (7bit XOR #50) AND #77

      Zone 3:          // BETA shift characters
          0x60 .. 0x7b (#140 .. #173, "ul" .. "lbrace" )
             => BETA, #40 .. #73
             so 6bit = BETA, 7bit AND #77
          0x7c .. 0x7f (#134 .. #137, "N2" .. "DEL")
             => DELTA, #70 .. #73
             so 6bit = DELTA, (7bit XOR #04) AND #77

(* the "zone" is normally the top 3 bits, but two works better for clarity).

6 bit to ECMA

      init:
          if (shifted) {
               shift = 0140;           # alpha
               delta = FALSE;
          }

      if (!shift) {
              switch (ch) {
                  case 000 ... 037:   // '0' ... '?'
                      return ch ^ 060;
                  case 040 ... 077;
                      return ch ^ 0140;
              }
      }
      else {
          if (delta) {
              switch (ch) {
                  case 000 ... 037:
                      output (ch ^ 020);  // control characters
                      break;
                  case 064 ... 067:
                      output (ch ^ 0150); // ^T => $
                      break;
                  case 070 .. 073:
                      output (ch + 0104); // ^X => |
                      break;
              }
              delta = false;
          }
          else {
              switch (ch) {
                  case 000 ... 037:       // characters same in ALPHA and BETA
                      output (ch ^ 060);
                      break;

                  case 040 ... 073;       // upper or lower case
                      output (ch ^ shift);
                      break;

                  case 074:
                      shift = 0140;   /* alpha */;
                      break;

                  case 075:
                      shift = 0100;   /* beta */
                      break;

                  case 076:
                      delta = true;
                      break;

                  case 077:          /* Filler character, ignore */
                      break;

             }
          }
      }