Search code examples
crandompicseven-segment-display

Random number generator with corresponding letter


I have 2 circuits, both made up of a dual seven segment display and A pic16f684 (As shown below) the first circuit uses the code supplied to generate a random number 1-26. The letter portion is the same circuit, but with one of the transistor removed, to disable one side. circuit

/*
 * File:   main.c
 * Original Code Creator: dan1138
 * Target: PIC16F684
 * Compiler: XC8 v2.20
 * IDE: MPLABX v5.25
 * 
 * Description:
 *
 * Created on July 21, 2020, 3:45 PM
 * 
 *                            PIC16F684
 *                  +------------:_:------------+
 *         GND -> 1 : VDD                   VSS : 14 <- 5v0
 * SEG_a_DRIVE <> 2 : RA5/T1CKI     PGD/AN0/RA0 : 13 <> DIGIT_DRIVE_2
 *         SW2 <> 3 : RA4/AN3       PGC/AN1/RA1 : 12 <> DIGIT_DRIVE_1
 *         SW1 -> 4 : RA3/VPP           AN2/RA2 : 11 <> 
 * SEG_b_DRIVE <> 5 : RC5/CPP1          AN4/RC0 : 10 <> SEG_g_DRIVE
 * SEG_c_DRIVE <> 6 : RC4/C2OUT         AN5/RC1 : 9  <> SEG_f_DRIVE
 * SEG_d_DRIVE <> 7 : RC3/AN7           AN6 RC2 : 8  <> SEG_e_DRIVE
 *                  +---------------------------:
 *                             DIP-14
 */

// CONFIG --- Configuration Word --- START
#pragma config FOSC = INTOSCIO
#pragma config WDTE = OFF
#pragma config PWRTE = OFF
#pragma config MCLRE = OFF
#pragma config CP = OFF
#pragma config CPD = OFF
#pragma config BOREN = OFF
#pragma config IESO = OFF
#pragma config FCMEN = OFF
// CONFIG --- Configuration Word --- END

#include <xc.h>
#include <stdlib.h>

/* Oscillator frequency we will select with the OSCCON register */
#define _XTAL_FREQ (4000000ul)
/*
 * Segment locations
 * of an LED display
 *      ---a---
 *     :       :
 *     f       b
 *     :       :
 *      ---g---
 *     :       :
 *     e       c
 *     :       :
 *      ---d---
 */
const unsigned char LEDDigit[] = {
//     abcdefg, Segment on = 0
    0b00000001, // "0"
    0b01001111, // "1"
    0b00010010, // "2"
    0b00000110, // "3"
    0b01001100, // "4"
    0b00100100, // "5"
    0b00100000, // "6"
    0b00001111, // "7"
    0b00000000, // "8"
    0b00001100, // "9"
    0b00001000, // "A"
    0b01100000, // "b"
    0b00110001, // "C"
    0b01000010, // "d"
    0b00110000, // "E"
    0b00111000  // "F"  
}; 



void main(void) 
{
    unsigned char DisplayValue, DisplayLED, DigitSegments;
    unsigned char LoopCount;
    unsigned int  Temp;
    
    PORTA = 0;
    PORTC = 0;
    CMCON0 = 7;                 // Turn off Comparators 
    ANSEL = 0;                  // Turn off ADC 
    
    __delay_ms(500);            // wait for ICD before making PGC and PGD outputs;
    TRISA = 0b011100;           // RA5, RA1, RA0 are outputs
    TRISC = 0b000000; 
    OPTION_REGbits.nRAPU = 0;   // Enable weak pull-up on PORTA
    WPUA = 0;                   // Turn off all pull-ups
    WPUAbits.WPUA4 = 1;         // Turn on RA4 pull-up
    
         
    DisplayValue = 0;           // Start Displaying at 0x00 
    DisplayLED = 0;             // Display the 1s first
    LoopCount = 0;
    srand(0x1234);
    
    for(;;)
    {
        PORTC = 0xFF;   // turn off all segment drivers
        PORTA = 0xFF;   // and digit drivers
        if (1 == (DisplayLED & 1))
        {
            DigitSegments = LEDDigit[(DisplayValue >> 4) & 0x0F];
            if(DigitSegments & 0b1000000)
                          {
                PORTA = 0b111110;   // turn on Digit driver 2
            } 
            else 
            {
                PORTA = 0b011110;   // turn on Digit driver 2 and SEG_a_DRIVER
            }
        }
        else
        {
            DigitSegments = LEDDigit[DisplayValue & 0x0F];
            if(DigitSegments & 0b1000000)
            {
                PORTA = 0b111101;   // turn on Digit driver 1
            } 
            else 
            {
                PORTA = 0b011101;   // turn on Digit driver 1 and SEG_a_DRIVER
            }
        }
        PORTC = DigitSegments;      // turn on segment drivers b to g
        DisplayLED++;               // select next digit

        __delay_ms(10);             // Show digit for 10 milliseconds
        
        if(0 == PORTAbits.RA3)      // is SW1 pressed?
        {
            LoopCount++;
            if(LoopCount == 1)
            {
                 // Display a new random value every 500 milliseconds
                Temp = rand() & 0xFFu;      // put random value in range of 0 to 255 and treat is as a fraction in range (0/256) <= value < (255/256)
                Temp = (Temp * 26u + 0x100u) >> 8; // Use tricky math to make a random number in the range from 1 to 56
                DisplayValue = (Temp / 10u) << 4;  // Extract the ten's digit
                DisplayValue = DisplayValue | (Temp % 10); // Extract the one's digit
            }
            if(LoopCount >= 50)
            {
                LoopCount = 0;
            }
        }
        else
        {
            LoopCount = 0;
        }

        if(0 == PORTAbits.RA4)      // is SW2 pressed?
        {
            DisplayValue = 0;       // Reset display value to zero
            LoopCount = 0;
        }
    }
}

My goal to is generate the corresponding letter on the second seven segment display using a modified alphabet. however, I cant figure out how to do this. My original thought was to output the temp value to the second pic16f684 with modified LEDDigits[];

const unsigned char LEDDigit[] = {
//     abcdefg, Segment on = 0
    0b01111110, //"-"
    0b00001000, // "A"
    0b01100000, // "b"
    0b00110001, // "C"
    0b01000010, // "d"
    0b00110000, // "E"
    0b00111000, // "F"  
    0b00100001, // "G"
    0b01001000, // "H"
    0b01111001, // "I"
    0b01000011, // "J"
    0b00101000, // "Modified K"
    0b01110001, // "L"
    0b00010101, // "Modified M"
    0b01101010, // "n"
    0b01100010, // "o"
    0b00011000, // "P"
    0b00001100, // "q"
    0b01111010, // "r"
    0b00100100, // "S"
    0b01110000, // "t"
    0b01100011, // "u"
    0b01010101, // "Modified V"
    0b01000000, // "Modified W"
    0b00110110, // "Modified X"
    0b01000100, // "y"
    0b00010010 // "Z"
        
}; 

But I dont believe I can just output that number. How can I display the number (1-26) on one dual display, and the corresponding letter on another display.

Could I potentially add the second seven segment display into the number circuit, set its transistor on RA2, and have it display the letter at the same time? how would this work?


Solution

  • Ok, so here is a solution for your homework:

    /*
     * File:   main.c
     * Author: dan1138
     * Target: PIC16F684
     * Compiler: XC8 v2.20
     * IDE: MPLABX v5.25
     * 
     * Description:
     * 
     * This code is the homework solution for Stack Overflow posts:
     *  https://stackoverflow.com/questions/63086495/random-number-generator-with-corresponding-letter
     *  https://stackoverflow.com/questions/63006839/pic16f684-dual-seven-seg-display-program-random-number-generator-in-c
     * 
     *
     * Created on July 21, 2020, 3:45 PM
     * 
     *                            PIC16F684
     *                  +------------:_:------------+
     *         GND -> 1 : VDD                   VSS : 14 <- 5v0
     * SEG_a_DRIVE <> 2 : RA5/T1CKI     PGD/AN0/RA0 : 13 <> DIGIT_DRIVE_2
     *         SW2 <> 3 : RA4/AN3       PGC/AN1/RA1 : 12 <> DIGIT_DRIVE_1
     *         SW1 -> 4 : RA3/VPP           AN2/RA2 : 11 <> DIGIT/ALPHAn mode
     * SEG_b_DRIVE <> 5 : RC5/CPP1          AN4/RC0 : 10 <> SEG_g_DRIVE
     * SEG_c_DRIVE <> 6 : RC4/C2OUT         AN5/RC1 : 9  <> SEG_f_DRIVE
     * SEG_d_DRIVE <> 7 : RC3/AN7           AN6 RC2 : 8  <> SEG_e_DRIVE
     *                  +---------------------------:
     *                             DIP-14
     */
    
    // CONFIG --- Configuration Word --- START
    #pragma config FOSC = INTOSCIO
    #pragma config WDTE = OFF
    #pragma config PWRTE = OFF
    #pragma config MCLRE = OFF
    #pragma config CP = OFF
    #pragma config CPD = OFF
    #pragma config BOREN = OFF
    #pragma config IESO = OFF
    #pragma config FCMEN = OFF
    // CONFIG --- Configuration Word --- END
    
    #include <xc.h>
    #include <stdlib.h>
    
    /* Oscillator frequency we will select with the OSCCON register */
    #define _XTAL_FREQ (4000000ul)
    /*
     * Segment locations
     * of an LED display
     *      ---a---
     *     :       :
     *     f       b
     *     :       :
     *      ---g---
     *     :       :
     *     e       c
     *     :       :
     *      ---d---
     */
    const unsigned char LEDDigitSegs[] = {
    //     abcdefg, Segment on = 0
        0b00000001, // "0"
        0b01001111, // "1"
        0b00010010, // "2"
        0b00000110, // "3"
        0b01001100, // "4"
        0b00100100, // "5"
        0b00100000, // "6"
        0b00001111, // "7"
        0b00000000, // "8"
        0b00001100, // "9"
        0b00001000, // "A"
        0b01100000, // "b"
        0b00110001, // "C"
        0b01000010, // "d"
        0b00110000, // "E"
        0b00111000  // "F"  
    }; 
    
    const unsigned char LEDAlphaSegs[] = {
    //     abcdefg, Segment on = 0
        0b01111110, // "-"
        0b00001000, // "A"
        0b01100000, // "b"
        0b00110001, // "C"
        0b01000010, // "d"
        0b00110000, // "E"
        0b00111000, // "F"  
        0b00100001, // "G"
        0b01001000, // "H"
        0b01111001, // "I"
        0b01000011, // "J"
        0b00101000, // "Modified K"
        0b01110001, // "L"
        0b00010101, // "Modified M"
        0b01101010, // "n"
        0b01100010, // "o"
        0b00011000, // "P"
        0b00001100, // "q"
        0b01111010, // "r"
        0b00100100, // "S"
        0b01110000, // "t"
        0b01100011, // "u"
        0b01010101, // "Modified V"
        0b01000000, // "Modified W"
        0b00110110, // "Modified X"
        0b01000100, // "y"
        0b00010010  // "Z"
    }; 
    
    void main(void) 
    {
        unsigned char Digit1_Segments, Digit2_Segments;
        unsigned char LoopCount;
        unsigned int  Temp;
    
        PORTA = 0xFF;
        PORTC = 0xFF;
        CMCON0 = 7;                 // Turn off Comparators 
        ANSEL = 0;                  // Turn off ADC 
    
        __delay_ms(500);            // wait for ICD before making PGC and PGD outputs;
        TRISA = 0b011111;           // RA5, RA1, RA0 are outputs
        TRISC = 0b000000; 
        OPTION_REGbits.nRAPU = 0;   // Enable weak pull-up on PORTA
        WPUA = 0;                   // Turn off all pull-ups
        WPUAbits.WPUA4 = 1;         // Turn on RA4 pull-up
        WPUAbits.WPUA2 = 1;         // Turn on RA2 pull-up
    
        Digit1_Segments = 0xFF;     // Turn off digit segments
        Digit2_Segments = 0xFF;     // Turn off digit segments
        LoopCount = 0;
        srand(0x1234);              // Seed the pseudo random number generator
    
        for(;;)
        {
            PORTC = 0xFF;   // turn off all segment drivers
            PORTA = 0xFF;   // and digit drivers
            if (TRISAbits.TRISA1 == 0)
            {
                TRISAbits.TRISA1 = 1;
                TRISAbits.TRISA0 = 1;
                if(0 == (Digit2_Segments & 0b1000000))
                {
                    PORTA = 0b011110;   // turn on Digit driver 2 and SEG_a_DRIVER
                }
                else
                {
                    PORTA = 0b111110;   // turn on Digit driver 2
                }
                PORTC = Digit2_Segments;      // turn on segment drivers b to g
                TRISAbits.TRISA0 = 0;;
            }
            else
            {
                TRISAbits.TRISA1 = 1;
                TRISAbits.TRISA0 = 1;
                if(0 == (Digit1_Segments & 0b1000000))
                {
                    PORTA = 0b011101;   // turn on Digit driver 1 and SEG_a_DRIVER
                }
                else
                {
                    PORTA = 0b111101;   // turn on Digit driver 1
                }
                PORTC = Digit1_Segments;      // turn on segment drivers b to g
                TRISAbits.TRISA1 = 0;;
            }
    
            __delay_ms(10);             // Show digit for 10 milliseconds
    
            if(0 == PORTAbits.RA3)      // is SW1 pressed?
            {
                LoopCount++;
                if(LoopCount == 1)
                {
                    // Display a new random value every 500 milliseconds
                    Temp = rand() & 0xFFu;      // put random value in range of 0 to 255 and treat is as a fraction in range (0/256) <= value < (255/256)
                    if(0 == PORTAbits.RA2)      // Choose between alpha and digits mode
                    {
                        // Show random character "A" to "Z" in digit 1, show dash "-" in digit 2
                        Temp = (Temp * 26u + 0x100u) >> 8; // Use tricky math to make a random number in the range from 1 to 26
                        Digit2_Segments = LEDAlphaSegs[0];    // Display a dash "-"
                        Digit1_Segments = LEDAlphaSegs[Temp]; // Display character segments (A-Z)
                    }
                    else
                    {
                        // Show two digit random number from 1 to 56
                        Temp = (Temp * 56u + 0x100u) >> 8; // Use tricky math to make a random number in the range from 1 to 56
                        Digit2_Segments = LEDDigitSegs[(Temp / 10)]; // Display the ten's digit segments
                        Digit1_Segments = LEDDigitSegs[(Temp % 10)]; // Display the one's digit segments
                    }
                }
                if(LoopCount >= 50)
                {
                    LoopCount = 0;
                }
            }
            else
            {
                LoopCount = 0;
            }
    
            if(0 == PORTAbits.RA4)      // is SW2 pressed?
            {
                Digit1_Segments = 0xFF;     // Turn off digit segments
                Digit2_Segments = 0xFF;     // Turn off digit segments
                LoopCount = 0;
            }
        }
    }
    

    If you instructor likes this please let me know what marks you received.