Advertisement
iskunk

Attempt at CM-5 "random and pleasing" pattern (rev. 4)

Apr 4th, 2016
83
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 3.81 KB | None | 0 0
  1. /* http://www.housedillon.com/?p=1272
  2.  * Written by iskunk (Daniel Richard G.)
  3.  * THIS FILE IS IN THE PUBLIC DOMAIN
  4.  *
  5.  * Program to emulate the CM-5's "random and pleasing" LED panel mode
  6.  * (revision 4)
  7.  */
  8.  
  9. #include <stdio.h>
  10. #include <stdint.h>
  11. #include <string.h>
  12. #include <unistd.h>
  13. #include <assert.h>
  14.  
  15. #define NUM_ROWS 32     /* unique rows */
  16. #define NUM_ROWS_DISPLAYED 106  /* rows in front panel display */
  17.  
  18. static uint16_t get_next_rnum_bit(uint16_t prev_rnum, uint16_t *pbit_out)
  19. {
  20. #define X prev_rnum
  21.  
  22.     /* https://en.wikipedia.org/wiki/Linear_feedback_shift_register
  23.      * Implementation of a primitive polynomial
  24.      */
  25.     uint16_t new_bit = ((X >> 0) ^ (X >> 1) ^ (X >> 3) ^ (X >> 12)) & 1;
  26.  
  27.     *pbit_out = (X | (X >> 2)) & 1;
  28.  
  29. #undef X
  30.  
  31.     return (new_bit << 15) | (prev_rnum >> 1);
  32. }
  33.  
  34. #ifndef NDEBUG
  35.  
  36. /* This is a rough translation of Jim's Intel 8741 assembler code into C
  37.  */
  38. static uint16_t get_next_rnum_bit_8741(uint16_t prev_rnum, uint16_t *pbit_out)
  39. {
  40.     uint8_t RNUM   = prev_rnum & 0xFF;  /* low-order byte */
  41.     uint8_t RNUMp1 = prev_rnum >> 8;    /* high-order byte */
  42.     uint8_t A, C, tmp;
  43.  
  44. #define GET_BIT(var, bit) ((var >> bit) & 1)
  45. #define cpl(reg) reg = reg ^ 1
  46. #define jnb(var, bit, label) if (!(var & (1 << bit))) goto label
  47. #define orl(reg, var, bit) reg |= ((var >> bit) & 1)
  48. #define rrc(reg) tmp = reg & 1; reg = (C << 7) | (reg >> 1); C = tmp
  49.  
  50.     /* ;This subroutine implements a 16 bit random number generator based
  51.      * ;on the primitive polynomial:
  52.      * ;
  53.      * ;    1 + X + X^3 + X^12 + X^16
  54.      * ;
  55.      * ;The value is stored in memory as RNUM.  This subroutine returns
  56.      * ;with the low order byte of the RNUM in the accumulator and a random
  57.      * ;bit value in the Carry (C) bit.
  58.      * ;
  59.      */
  60.     C = GET_BIT(RNUM, 0);   /* mov C, RNUM.0        ;get the units value of the PP      */
  61.     jnb(RNUM, 1, rand1);    /* jnb RNUM.1, rand1        ;jmp if X = 0               */
  62.     cpl(C);         /* cpl C            ;else compliment C (xor)        */
  63. rand1:  jnb(RNUM, 3, rand2);    /* jnb RNUM.3, rand2        ;jmp if X^3 = 0             */
  64.     cpl(C);         /* cpl C            ;else compliment C (xor)        */
  65. rand2:  jnb(RNUMp1, 4, rand3);  /* jnb (RNUM+1).4, rand3    ;jmp if X^12 = 0            */
  66.     cpl(C);         /* cpl C            ;else compliment C (xor)        */
  67. rand3:  A = RNUMp1;     /* mov A, RNUM+1        ;get high byte of RNUM          */
  68.     rrc(A);         /* rrc A            ;and rotate down (thru accumulator) */
  69.     RNUMp1 = A;     /* mov RNUM+1, A        ;save it back to memory         */
  70.     A = RNUM;       /* mov A, RNUM          ;get low byte of RNUM           */
  71.     rrc(A);         /* rrc A            ;and rotate down (thru accumulator) */
  72.     RNUM = A;       /* mov RNUM, A          ;save it back to memory         */
  73.     orl(C, RNUM, 1);    /* orl C, RNUM.1        ;set C only 25 percent of the time  */
  74.                 /* ret              ;return                 */
  75.  
  76.     *pbit_out = C;
  77.  
  78. #undef GET_BIT
  79. #undef cpl
  80. #undef jnb
  81. #undef orl
  82. #undef rrc
  83.  
  84.     return RNUM | (RNUMp1 << 8);
  85. }
  86.  
  87. #endif /* !NDEBUG */
  88.  
  89. static void print_row(uint16_t x)
  90. {
  91.     uint16_t m;
  92.     int pos;
  93.     char v[17];
  94.  
  95.     /* 0 -> LED on, 1 -> LED off */
  96.     for (m = 1 << 15, pos = 0; m != 0; m >>= 1, pos++)
  97.         v[pos] = (x & m) ? '-' : 'O';
  98.  
  99.     v[16] = '\0';
  100.  
  101.     puts(v);
  102. }
  103.  
  104. int main(void)
  105. {
  106.     uint16_t rnum = 1;
  107.     uint16_t rows[NUM_ROWS];
  108.     int i;
  109.  
  110.     memset(rows, 0, sizeof(rows));
  111.  
  112.     for (;;)
  113.     {
  114.         for (i = 0; i < NUM_ROWS; i++)
  115.         {
  116.             uint16_t rnum_new, bit = 0;
  117.             rnum_new = get_next_rnum_bit(rnum, &bit);
  118.  
  119.             if (i & 4)
  120.                 rows[i] = (bit << 15) | (rows[i] >> 1);
  121.             else
  122.                 rows[i] = (rows[i] << 1) | bit;
  123.  
  124. #ifndef NDEBUG
  125.             {
  126.                 uint16_t rnum_new_8741, bit_8741 = 0;
  127.                
  128.                 rnum_new_8741 = get_next_rnum_bit_8741(rnum, &bit_8741);
  129.  
  130.                 assert(rnum_new == rnum_new_8741);
  131.                 assert(bit      == bit_8741);
  132.             }
  133. #endif
  134.  
  135.             rnum = rnum_new;
  136.         }
  137.  
  138.         /* ANSI sequence to clear terminal */
  139.         fputs("\033[2J\033[1;1H", stdout);
  140.  
  141.         for (i = 0; i < NUM_ROWS_DISPLAYED; i++)
  142.             print_row(rows[i & 31]);
  143.  
  144.         fflush(stdout);
  145.         usleep(200000);
  146.     }
  147.  
  148.     return 0;
  149. }
  150.  
  151. /* EOF */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement