Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* http://www.housedillon.com/?p=1272
- * Written by iskunk (Daniel Richard G.) 2016 April
- * printf("<%s@%s.%s>\n", "skunk", "iskunk", "org");
- * THIS FILE IS IN THE PUBLIC DOMAIN
- *
- * Program to emulate a subset of the Thinking Machines Corp. CM-5 front
- * LED panel display modes (revision 6)
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <stdint.h>
- #include <string.h>
- #include <unistd.h>
- #include <assert.h>
- #define NUM_ROWS 32 /* unique rows */
- #define NUM_ROWS_HALF 16 /* NUM_ROWS divided by 2 */
- #define NUM_ROWS_DISPLAYED 106 /* total rows in front panel display */
- #define RNUM_SEED 0xBAD /* :-) */
- static uint16_t rnum = RNUM_SEED;
- static uint16_t rnum_8741 = RNUM_SEED;
- /* A Galois LFSR requires a different seed to produce the same output
- */
- static uint16_t rnum_galois = 0x917D;
- /* Note: rows[0] is the top row; most significant bit is at left;
- * a zero bit corresponds to a lit LED
- */
- static uint16_t rows[NUM_ROWS];
- /* Uninitialized bits, displayed briefly at the start of mode 7
- */
- static const uint16_t rows_glitch[NUM_ROWS] = {
- 0x8F10, 0x9112, 0x9314, 0x9516, 0x18E9, 0x5899, 0x38D9, 0x78B9,
- 0x9F20, 0xA122, 0xA324, 0xA526, 0x14E5, 0x5495, 0x34D5, 0x74B5,
- 0xAF30, 0xB132, 0xB334, 0xB536, 0x1CED, 0x5C9D, 0x3CDD, 0x7CBD,
- 0xBF40, 0xC142, 0xC344, 0xC546, 0x12E3, 0x5293, 0x32D3, 0x72B3
- };
- /* This is a rough translation of Jim's Intel 8741 assembler code into C.
- * His original code and (lightly edited) comments are retained below.
- */
- static uint16_t get_random_bit_8741(void)
- {
- uint8_t RNUM = rnum_8741 & 0xFF; /* low-order byte */
- uint8_t RNUMp1 = rnum_8741 >> 8; /* high-order byte */
- uint8_t A, C, tmp;
- #define b(var, n) ((var >> n) & 1) /* gets Nth bit */
- #define cpl(flag) flag = flag ^ 1
- #define jnb(val, label) if (!val) goto label
- #define orl(flag, val) flag |= val
- #define rrc(reg) tmp = reg & 1; reg = (C << 7) | (reg >> 1); C = tmp
- /* ;This subroutine implements a 16 bit random number generator based
- * ;on the primitive polynomial:
- * ;
- * ; 1 + X + X^3 + X^12 + X^16
- * ;
- * ;The value is stored in memory as RNUM. This subroutine returns
- * ;with the low order byte of the RNUM in the accumulator and a random
- * ;bit value in the Carry (C) bit.
- * ;
- */
- C = b(RNUM,0); /* mov C, RNUM.0 ;get the units value of the PP */
- jnb(b(RNUM,1), rand1); /* jnb RNUM.1, rand1 ;jmp if X = 0 */
- cpl(C); /* cpl C ;else compliment C (xor) */
- rand1: jnb(b(RNUM,3), rand2); /* jnb RNUM.3, rand2 ;jmp if X^3 = 0 */
- cpl(C); /* cpl C ;else compliment C (xor) */
- rand2: jnb(b(RNUMp1,4), rand3); /* jnb (RNUM+1).4, rand3 ;jmp if X^12 = 0 */
- cpl(C); /* cpl C ;else compliment C (xor) */
- rand3: A = RNUMp1; /* mov A, RNUM+1 ;get high byte of RNUM */
- rrc(A); /* rrc A ;and rotate down (thru accumulator) */
- RNUMp1 = A; /* mov RNUM+1, A ;save it back to memory */
- A = RNUM; /* mov A, RNUM ;get low byte of RNUM */
- rrc(A); /* rrc A ;and rotate down (thru accumulator) */
- RNUM = A; /* mov RNUM, A ;save it back to memory */
- orl(C, b(RNUM,1)); /* orl C, RNUM.1 ;set C 75 percent of the time */
- /* ret ;return */
- #undef b
- #undef cpl
- #undef jnb
- #undef orl
- #undef rrc
- rnum_8741 = RNUM | (RNUMp1 << 8);
- return C;
- }
- /* "In a software implementation of an LFSR, the Galois form is more
- * efficient as the XOR operations can be implemented a word at a
- * time: only the output bit must be examined individually."
- * -- https://en.wikipedia.org/wiki/Linear_feedback_shift_register
- */
- static uint16_t get_random_bit_galois(void)
- {
- #define X rnum_galois
- uint16_t out_bit = X & 1;
- uint16_t rand_bit = (X | (X >> 2)) & 1;
- X >>= 1;
- X ^= (-out_bit) & 0xD008;
- #undef X
- return rand_bit;
- }
- static uint16_t get_random_bit(void)
- {
- #define X rnum
- /* https://en.wikipedia.org/wiki/Linear_feedback_shift_register
- * Primitive polynomial: x^16 + x^15 + x^13 + x^4 + 1
- */
- uint16_t lfsr_bit = ((X >> 0) ^ (X >> 1) ^ (X >> 3) ^ (X >> 12)) & 1;
- uint16_t rand_bit = (X | (X >> 2)) & 1;
- X = (lfsr_bit << 15) | (X >> 1);
- #undef X
- #ifndef NDEBUG
- /* Compare two alternative implementations of the pseudo-random bit
- * generator function */
- {
- uint16_t rand_bit_8741 = get_random_bit_8741();
- uint16_t rand_bit_galois = get_random_bit_galois();
- assert(rand_bit == rand_bit_8741);
- assert(rand_bit_galois == rand_bit);
- assert(rnum == rnum_8741);
- }
- #endif
- return rand_bit;
- }
- static void print_row(uint16_t x)
- {
- uint16_t m;
- int pos;
- char v[17];
- /* MSB at left, LSB at right
- * 0 -> LED on, 1 -> LED off
- */
- for (m = 1 << 15, pos = 0; m != 0; m >>= 1, pos++)
- v[pos] = (x & m) ? '-' : 'O';
- v[16] = '\0';
- puts(v);
- }
- static void print_panel(void)
- {
- int i;
- /* ANSI escape sequence to clear screen
- */
- fputs("\033[2J\033[1;1H", stdout);
- for (i = 0; i < NUM_ROWS_DISPLAYED; i++)
- print_row(rows[i & 31]);
- }
- int main(int argc, char **argv)
- {
- int mode = 7;
- int i, j;
- int toggle = 0;
- if (argc == 2)
- {
- mode = (int)strtol(argv[1], NULL, 16);
- switch (mode)
- {
- case 5:
- case 7:
- case 9:
- case 0xA:
- case 0xB:
- break;
- default:
- printf("error: invalid mode \"%s\"\n", argv[1]);
- printf("usage: %s [MODE]\n", argv[0]);
- puts("valid options for MODE: 5 7 9 A B");
- return 1;
- }
- }
- /* Initial state: all but 3 LEDs lit
- */
- memset(rows, 0, sizeof(rows));
- rows[0] = 0x9400;
- print_panel();
- fflush(stdout);
- usleep(600000); /* 600 ms */
- /* Initialize rows with glitch pattern
- */
- memcpy(rows, rows_glitch, sizeof(rows));
- for (;;)
- {
- switch (mode)
- {
- /* "random and pleasing" */
- case 5:
- for (i = 0; i < NUM_ROWS_HALF; i++)
- {
- for (j = 0; j < 16; j++)
- {
- /* Note that the upper half of the
- * panel is one JTAG chain, and the
- * lower half is another */
- uint16_t bit_lower = get_random_bit();
- uint16_t bit_upper = get_random_bit();
- rows[i] <<= 1;
- rows[i] |= bit_upper;
- rows[i + NUM_ROWS_HALF] <<= 1;
- rows[i + NUM_ROWS_HALF] |= bit_lower;
- }
- }
- break;
- /* "interleaved display of random and pleasing" */
- case 7:
- for (i = NUM_ROWS - 1; i >= 0; i--)
- {
- uint16_t bit = get_random_bit();
- if (i & 4)
- rows[i] = (bit << 15) | (rows[i] >> 1);
- else
- rows[i] = (rows[i] << 1) | bit;
- }
- break;
- /* "all leds on" */
- case 9:
- memset(rows, 0, sizeof(rows));
- break;
- /* "all leds off" */
- case 0xA:
- memset(rows, 0xFF, sizeof(rows));
- break;
- /* "continuous blink leds on then off" */
- case 0xB:
- memset(rows, toggle ? 0 : 0xFF, sizeof(rows));
- toggle ^= 1;
- break;
- }
- print_panel();
- fflush(stdout);
- usleep(200000); /* 200 ms */
- }
- return 0;
- }
- /* EOF */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement