Home .. Personal .. ARTICLES .. Software .. MUD .. Links .. Search
SUPPORTING 1200/75 BAUD
The method presented below will allow you to simulate a serial port which
can send at 75 baud and receive at 1200 baud. 1200/75 is very popular in the
UK, and is usually the only speed available for viewdata services.
Translating a single character 75 baud character = S10101010E The ideal representation of this at 1200 baud is: 0000000000000000 1111111111111111 0000000000000000 1111111111111111 0000000000000000 1111111111111111 0000000000000000 1111111111111111 0000000000000000 1111111111111111 But the nearest approximation that can be obtained, taking into account start and stop bits is: S00000000ES00000 111ES11111111ES1 0000000ES0000000 1ES11111111ES111 00000ES00000000E S11111111ES11111 000ES00000000ES0 1111111ES1111111 0ES00000000ES000 11111ES11111111E Extracting the data part of each character (the bits between each S and E) gives the bytes which must be sent at 1200 baud to reproduce the original 75 baud character. The 16 bytes are: +0 +1 +2 +3 0: 00000000 00000111 11111111 10000000 4: 00000001 11111111 11100000 00000000 8: 11111111 11111000 00000000 01111111 12: 11111110 00000000 00011111 11111111 From this, it is apparent that bytes 0, 2, 5, 7, 8, 10, 13, 15 are all equal to the value of one the of bits in the original byte. The bits in the original byte are laid out as follows: Pos: 0123456789 Value: S10101010E In fact, the correlation is as follows: Byte Num: 0 2 5 7 8 10 13 15 Bit Pos: 0 1 3 4 5 6 8 9 This leaves the bytes 1, 3, 4, 5, 9, 11, 12, 14 to be filled in. The values for these bytes are a little more complicated. The calculation can be simplified by noting that the conversion procedure for the second four bytes is identical to that for the first four bytes: Byte 1 : [7..3] = bit 0, [2..0] = bit 1 Byte 3 : [7..7] = bit 1, [6..0] = bit 2 Byte 4 : [7..1] = bit 2, [0..0] = bit 3 Byte 6 : [7..5] = bit 3, [4..0] = bit 4 Byte 9 : [7..3] = bit 5, [2..0] = bit 6 Byte 11: [7..7] = bit 6, [6..0] = bit 7 Byte 12: [7..1] = bit 7, [0..0] = bit 8 Byte 14: [7..5] = bit 8, [4..0] = bit 9
However, although this method will give a good approximation of the
75 baud character, it is not perfect. It is possible for a solitary stop bit
to occur between two '0' bits for example, which will effectively cause a
spike in the signal. Depending on the position of this spike relative to
the start of the current 75 baud 'bit' being sent, this may or may not
confuse the receiving modem.
Sample code /* * Standard types used throughout */ typedef ULONG unsigned long int; /* 32 bit type */ typedef UWORD unsigned short int; /* 16 bit type */ /* * BuildConv75to1200() * * Sample source code to convert a single 8-bit * character into a 16-byte array, so that * sending the contents of the array at 1200 * baud will have a similar effect to sending * the original character at 75 baud. * * Some smoothing of the output is done to * prevent confusing the host - otherwise, some * combinations of 0101 can occur which lead to * invalid characters. * * A translation table is built, to speed up * the conversion. This table uses the fact * that the conversion procedure for the first * five bits is identical to that for the * remaining five bits, so only 32 eight byte * sets need be stored. * * The Conv75to1200() routine uses the lookup * tables, therefore you must call this * BuildConv75To1200() before making calls to * Conv75to1200(). */ ULONG ConvLow[32], ConvHigh[32]; UWORD Power[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x100, 0x200 }; UWORD Left[] = { 0, 0xF8, 0, 0x80, 0xFE, 0, 0xE0, 0, 0, 0xF8, 0, 0x80, 0xFE, 0, 0xE0, 0 }; UWORD Right[] = { 0, 0x07, 0, 0x7F, 0x01, 0, 0x1F, 0, 0, 0x07, 0, 0x7F, 0x01, 0, 0x1F, 0 }; #define EasyBit(pos) \ ((outbyte & Power[pos]) ? 0xFF : 0x00 ) #define HardBit(x,pos) \ ( ((outbyte & Power[pos]) ? Left[x] : 0x00 ) | \ ((outbyte & Power[pos+1]) ? Right[x] : 0x00) ) void BuildConv75to1200() { unsigned char out[16]; UWORD outbyte; ULONG *longout; int i; longout = (ULONG *)out; for (i = 0; i < 32; i += 2) { /* * Generate 10-bit byte */ outbyte = i | ((i+1) << 5); out[0] = EasyBit(0); out[2] = EasyBit(1); out[5] = EasyBit(3); out[7] = EasyBit(4); out[8] = EasyBit(5); out[10] = EasyBit(6); out[13] = EasyBit(8); out[15] = EasyBit(9); out[1] = HardBit( 1, 0); out[3] = HardBit( 3, 1); out[4] = HardBit( 4, 2); out[6] = HardBit( 6, 3); out[9] = HardBit( 9, 5); out[11] = HardBit(11, 6); out[12] = HardBit(12, 7); out[14] = HardBit(14, 8); /* * Now smooth out any spikes in the signal */ if (out[3] == 0x80) out[3] = 0x00; if (out[3] == 0x7f) out[3] = 0xff; if (out[11] == 0x80) out[11] = 0x00; if (out[11] == 0x7f) out[11] = 0xff; if (out[4] == 0xFE) out[4] = 0xFF; if (out[4] == 0x01) out[4] = 0x00; if (out[12] == 0xFE) out[12] = 0xFF; if (out[12] == 0x01) out[12] = 0x00; /* * Store eight bytes equivalent for * each pair of five bits */ ConvLow[i] = longout[0]; ConvHigh[i] = longout[1]; ConvLow[i+1] = longout[2]; ConvHigh[i+1] = longout[3]; } } /* * Conv75to1200() * * Converts character ch to be sent at 75 baud * into 16 bytes which can be sent at 1200 baud * for the same effect. Out is a pointer to an * array of four longwords where the output data * is stored. The lookup table generated in * BuildConv75to1200() is used for speed. * */ void Conv75to1200(unsigned char ch, ULONG out[]) { UWORD conv; int lownibble; int hinibble; /* * Add start & stop bits to ch */ conv = (UWORD)ch + (UWORD)ch + 0x200; lownibble = (conv & 0x1F); hinibble = (conv >> 5); /* * Now perform the conversion using the table */ out[0] = ConvLow[lownibble]; out[1] = ConvHigh[lownibble]; out[2] = ConvLow[hinibble]; out[3] = ConvHigh[hinibble]; } /* * Conv75to1200() * * This is a macro version of the above * function. 'conv', 'ln' and 'hn' must be * previously defined as UWORD, preferably * as register vars. 'Out' is a pointer to * an array of 4 ULONGs and ch is a character. * (Yes, it's a bit of a kludge; sorry!) */ #define Conv75to1200(ch,out) \ { conv = ch + ch + 0x200; \ ln = conv & 0x1F; \ hn = conv >> 5; \ out[0] = ConvLow[ln]; \ out[1] = ConvHigh[ln]; \ out[2] = ConvLow[hn]; \ out[3] = ConvHigh[hn]; \ } /* * End of sample conversion code */
Home .. Personal .. ARTICLES .. Software .. MUD .. Links .. Search |