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.)
- * THIS FILE IS IN THE PUBLIC DOMAIN
- *
- * Program to emulate the CM-5's "random and pleasing" LED panel mode
- * (revision 5, "House Dillon video exclusive" edition)
- */
- #include <stdio.h>
- #include <stdint.h>
- #include <string.h>
- #include <unistd.h>
- #include <assert.h>
- #define NUM_ROWS 32 /* unique rows */
- #define NUM_ROWS_DISPLAYED 106 /* rows in front panel display */
- /* Dillon's video shows a single 16x32 panel */
- #undef NUM_ROWS_DISPLAYED
- #define NUM_ROWS_DISPLAYED 32
- #ifndef NDEBUG
- # define COMPARE_8741
- #endif
- #define RNUM_SEED 0xBAD
- static uint16_t rnum = RNUM_SEED;
- static uint16_t rnum_8741 = RNUM_SEED;
- /* 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];
- /* The source of this pattern is not [yet] known. Note that all these rows
- * will be shifted by one bit before being displayed.
- */
- static const uint16_t rows_mystery[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
- };
- 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;
- #undef X
- rnum = (lfsr_bit << 15) | (rnum >> 1);
- return rand_bit;
- }
- /* This is a rough translation of Jim's Intel 8741 assembler code into C
- */
- 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 ;light LED only 25 percent of the time */
- /* ret ;return */
- #undef b
- #undef cpl
- #undef jnb
- #undef orl
- #undef rrc
- rnum_8741 = RNUM | (RNUMp1 << 8);
- return C;
- }
- static void print_row(uint16_t x)
- {
- uint16_t m;
- int pos;
- char v[17];
- /* 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 sequence to clear terminal */
- fputs("\033[2J\033[1;1H", stdout);
- for (i = 0; i < NUM_ROWS_DISPLAYED; i++)
- print_row(rows[i & 31]);
- }
- int main(void)
- {
- int i;
- int t = 2;
- /* 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 mystery pattern */
- memcpy(rows, rows_mystery, sizeof(rows));
- for (;;)
- {
- for (i = NUM_ROWS - 1; i >= 0; i--)
- {
- uint16_t bit = get_random_bit();
- #ifdef COMPARE_8741
- uint16_t bit_8741 = get_random_bit_8741();
- assert(bit == bit_8741);
- assert(rnum == rnum_8741);
- #endif
- if (i & 4)
- rows[i] = (bit << 15) | (rows[i] >> 1);
- else
- rows[i] = (rows[i] << 1) | bit;
- }
- print_panel();
- /* Print timestamp for matching to Dillon's video */
- if (++t < 300)
- printf("\n00:00:%02d:%02d\n", t / 5, 6 * (t % 5));
- fflush(stdout);
- usleep(200000); /* 200 ms */
- }
- return 0;
- }
- /* EOF */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement