Maximal Length Shift Register - Working code

Discussion on projects that are created by users and posted on mikroElektronika website.
Post Reply
Author
Message
Bill Legge
Posts: 235
Joined: 28 Oct 2007 03:16
Location: West Australia

Maximal Length Shift Register - Working code

#1 Post by Bill Legge » 09 Aug 2021 03:39

A bit of fun here - look up 'Maximal Length Shift Registers'
The idea is to chain 8bit registers together, select some of the registers, feed into an XOR gate and feedback the output of the XOR gate into register zero
I chose to use eight 8 bit shift registers (giving 64 registers numbered 0 to 63) and take the output of registers 61 and 62 to drive the XOR gate.
See the attached drawing 'Shift Register 1'
The shift gates are controlled by a PIC18F46K22 on an Olimex40 pin board. See drawing 'Olimex Shift Register.'
The stream of 1s and 0s have some surprising properties:
  • Quasi-random with a cycle length that is amazingly long - thousands of years when run at 100MHz.
  • Statistics - The probability of consecutive 1s is 50%. So, if 30 consecutive 1s occur 42 times, consecutive 29 will occur 21 times - and so on.
If you use the register outputs to drive LEDS (as I have) watch out for a fairly high current consumption at high shift speeds - about 500mA.
The code is below along with the two drawings

Code: Select all

////////////////////////////////////////////////////////////////////////////////
// Project:         Shift Register                                            //
// File:            Shift_Register.c                                          //
// Function:        Drive the 74HC595 8bit shift registers in a 64bit chain   //
//                  with feedback taps at 61 and 62                           //
// MCU:             PIC18F64K22                                               //
// Board:           Olimex 40 pin                                             //
// Power            5V                                                        //
// Compiler:        mikroC PRO for PIC version 7.6.0                          //
// Programmer:      ICD3                                                      //
// Author:          WVL                                                       //
// Date:            August 2021                                               //
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
// 74HC595 8_bit shift register:                                              //
//    1. CMOS to 57MHz                                                        //
//    2. ENABLE active low                                                    //
//    3. RESET active low                                                     //
//    4. CLOCK edge is L->H                                                   //
//    5. LATCH L->H puts previous state of register onto parallel op          //
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
// Defines                                                                    //
#define RESET       LATB3_bit   // Master reset                               //
#define CLOCK       LATB2_bit   // CLOCK                                      //
#define LATCH       LATB1_bit   // LATCH                                      //
#define DATA_OUT    LATB0_bit   // DATA to shift registers                    //
#define DATA_IN     PORTB.B0    // Set if 1 is output by the XOR gate         //
#define LED_RED     LATA0_bit                                                 //                                                //
#define LED_GREEN   LATA2_bit                                                 //
#define LED_YELLOW  LATA3_bit                                                 //
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
// function - send PrintOut stream to the PC via UART1                        //
void PCTU1(char c){                                                           //
    UART1_Write(c);                                                           //
}                                                                             //
////////////////////////////////////////////////////////////////////////////////

sbit FASTER at PORTC.B0;                // white button active low
sbit SLOWER at PORTC.B1;                // yellow button active low

void main() {
    unsigned int           x = 0;
    unsigned int       count = 0;       // index of array 'consecutive_1s'
    unsigned int     delay = 100;       // delay in mS
    unsigned long consecutive_1s[64];   // record number of consecutive pulses
    unsigned long pulses = 0;           // count of all is and os
    // Ports and pins
    ANSELA = 0b00000000;    // 1=analog 0=digital
    ANSELB = 0b00000000;    // 1=analog 0=digital
    ANSELC = 0b00000000;    // 1=analog 0=digital
    ANSELD = 0b00000000;    // 1=analog 0=digital
    ANSELE = 0b00000000;    // 1=analog 0=digital
    WPUB   = 0b00000000;    // pull up 1=enabled 0=disabled
    TRISA  = 0b11110010;    // LEDs on RA0,RA2,RA3
    TRISB  = 0b00000000;    // B1 LATCH, B2 CLOCK, B3 RESET, B4 DATA OUT
    TRISC  = 0b00000011;    // C0 BUTTON UP, C1 BUTTON DN, C6 RX RS232, C7 TX RS232
    TRISD  = 0b11111111;    // all inputs. RD2 detects op of shift register 63
    TRISE  = 0b11111111;    // Unused all inputs
    // Peripherals
    PMD1 = 0b00011111;      // CCP1MD to CCP5MD off
    UART1_Init(57600);      // use RC6/Tx1 RC7/Rx1
    delay_ms(5);
    UART1_Write_Text("Shift Register at 80MHz\r\n");
    delay_ms(100);

    // Set initial conditions
    CLOCK  = 0;
    LATCH  = 0;
    // Empty the registers
    RESET  = 0;
    // Initial shift register conditions
    CLOCK  = 0;
    LATCH  = 0;
    RESET  = 1;     // cancell the reset
    // Load 1 into first shift register and start shifting
    DATA_OUT   = 1; // logic 1 at input
    CLOCK      = 1; // all registers shift once
    LATCH      = 1; // move data from registers to display
    CLOCK      = 0;
    LATCH      = 0;
    DATA_OUT   = 0;
    TRISB0_bit = 1; // float data pin so XOR drives from now on
    
    for(x=0;x<=63;x++){
        consecutive_1s[x] = 0;
    }
    
    while(1){
        if(FASTER==0){
            LED_GREEN = 1;
            delay = delay>>1;
            if(delay<= 2)delay = 1;
            }
        else LED_GREEN = 0;
        if(SLOWER==0){
            LED_YELLOW = 1;
            delay = delay<<1;
            if(delay>=1000)delay = 1000;
            }
        else LED_YELLOW = 0;

        // Move the data one space along the shift registers
        CLOCK  = 1;
        CLOCK  = 0;
        LATCH  = 1;
        LATCH  = 0;

        // Count consecutive '1s'
        if(DATA_IN==1){
            LED_RED = 1;
            count ++;
            consecutive_1s[count]++;
            if(count>63)count=63;
        }
        else{
            count=0;
            LED_RED = 0;
        }
        
        // Send data to pc every 10,000 cycles
        if(pulses%10000==0){
            Printout(PCTU1,"Total Pulses:\t%Lu\r\n",pulses);
            for(x=1;x<=63;x++){
                if(consecutive_1s[x]==0)break;  // don't print zero results
                Printout(PCTU1,"Pulse_count %u\t %Lu\r\n",x,consecutive_1s[x]);
            }
        }
        
        // Housekeeping
        pulses++;
        Vdelay_ms(delay);
    }
}
A similar circuit may be used as a noise generator - see the excellent book 'The Art of Electronics' by Horowitz and Hill.
Good luck from Bill Legge in Australia
Attachments
Shift_register_01.pdf
(81.33 KiB) Downloaded 82 times
Olimex Shift Register.pdf
(129.48 KiB) Downloaded 76 times

Post Reply

Return to “User Projects”