EEVblog Electronics Community Forum

Products => Computers => Programming => Topic started by: Szabolcs on September 11, 2020, 08:20:16 pm

Title: RASPBERRY PI C
Post by: Szabolcs on September 11, 2020, 08:20:16 pm
Hy!

1. It was loong time that i used this forum. I had to create new accaunt.

2. Sorry for bad eng i type at night after work. So my brain is not working sometime.

3. What I want ! I want to create C programs that communicate with Raspberry pi hats and other stuff . YES I KNOW THERE IS PHYTON code for evriting.

Title: Re: RASPBERRY PI C
Post by: Szabolcs on September 11, 2020, 08:28:09 pm
My forst projekt is to wirte driver for  SH1107 https://shop.pimoroni.com/products/1-12-oled-breakout?variant=12628508704851

Not using Wiering pi. bc I don't know how long will last.

MY CODE BITBANG because using SPI it wont let me use most of the io pins (or I am wrong)-- i try to use the simplest code

//compaile pi@TOSTER:~ $ sudo gcc -o dis -l rt display.c -l bcm2835
#include <stdio.h>
#include <bcm2835.h>
// bcm2835_delayMicroseconds()
// Blinks on RPi Plug P1 pin 11 (which is GPIO pin 17)
#define MOSI RPI_GPIO_P1_19    //MOSI DATA 8 bit
#define SCK RPI_GPIO_P1_23    //SCK Clock
#define SS_CS RPI_GPIO_P1_24 //CS Slave slect
#define CD RPI_GPIO_P1_21   //CD command select MISO

// function to convert Hexadecimal to Binary Number
int J;

void DEF ()

{

   bcm2835_init();
   
   bcm2835_gpio_fsel(CD, BCM2835_GPIO_FSEL_OUTP);
    bcm2835_gpio_fsel(SS_CS, BCM2835_GPIO_FSEL_OUTP);
   bcm2835_gpio_fsel(MOSI, BCM2835_GPIO_FSEL_OUTP);
   bcm2835_gpio_fsel(SCK, BCM2835_GPIO_FSEL_OUTP);
 
   bcm2835_gpio_write(CD, LOW);
   bcm2835_gpio_write(SS_CS, LOW);
   bcm2835_gpio_write(MOSI, LOW);
   bcm2835_gpio_write(SCK, LOW);
      bcm2835_close();


   
}


void SPI8(char* hexdec)
{
    int DATA [8]; //8 biten megy a kommmunikáció
   
            switch (hexdec[0]) {
        case '0':
            DATA
            DATA [1] = 0;
            DATA [2] = 0;
            DATA [3] = 0;
            break;
        case '1':
            DATA
            DATA [1] = 0;
            DATA [2] = 0;
            DATA [3] = 1;
            break;
        case '2':
            DATA
            DATA [1] = 0;
            DATA [2] = 1;
            DATA [3] = 0;
            break;
        case '3':
            DATA
            DATA [1] = 0;
            DATA [2] = 1;
            DATA [3] = 1;
            break;
        case '4':
            DATA
            DATA [1] = 1;
            DATA [2] = 0;
            DATA [3] = 0;
            break;
        case '5':
            DATA
            DATA [1] = 1;
            DATA [2] = 0;
            DATA [3] = 1;
            break;
        case '6':
            DATA
            DATA [1] = 1;
            DATA [2] = 1;
            DATA [3] = 0;
            break;
        case '7':
            DATA
            DATA [1] = 1;
            DATA [2] = 1;
            DATA [3] = 1;
            break;
        case '8':
            DATA
            DATA [1] = 0;
            DATA [2] = 0;
            DATA [3] = 0;
            break;
        case '9':
            DATA
            DATA [1] = 0;
            DATA [2] = 0;
            DATA [3] = 1;
            break;
        case 'A':
        case 'a':
            DATA
            DATA [1] = 0;
            DATA [2] = 1;
            DATA [3] = 0;
            break;
        case 'B':
        case 'b':
            DATA
            DATA [1] = 0;
            DATA [2] = 1;
            DATA [3] = 1;
            break;
        case 'C':
        case 'c':
            DATA
            DATA [1] = 1;
            DATA [2] = 0;
            DATA [3] = 0;
            break;
        case 'D':
        case 'd':
            DATA
            DATA [1] = 1;
            DATA [2] = 0;
            DATA [3] = 1;
            break;
        case 'E':
        case 'e':
            DATA
            DATA [1] = 1;
            DATA [2] = 1;
            DATA [3] = 0;
            break;
        case 'F':
        case 'f':
            DATA
            DATA [1] = 1;
            DATA [2] = 1;
            DATA [3] = 1;
            break;
        default:
      break;
           // printf("\nInvalid hexadecimal digit %c",
           //        hexdec[0]);
        }
       
            switch (hexdec[1]) {
        case '0':
            DATA [4] = 0;
            DATA [5] = 0;
            DATA [6] = 0;
            DATA [7] = 0;
            break;
        case '1':
            DATA [4] = 0;
            DATA [5] = 0;
            DATA [6] = 0;
            DATA [7] = 1;
            break;
        case '2':
            DATA [4] = 0;
            DATA [5] = 0;
            DATA [6] = 1;
            DATA [7] = 0;
            break;
        case '3':
            DATA [4] = 0;
            DATA [5] = 0;
            DATA [6] = 1;
            DATA [7] = 1;
            break;
        case '4':
            DATA [4] = 0;
            DATA [5] = 1;
            DATA [6] = 0;
            DATA [7] = 0;
            break;
        case '5':
            DATA [4] = 0;
            DATA [5] = 1;
            DATA [6] = 0;
            DATA [7] = 1;
            break;
        case '6':
            DATA [4] = 0;
            DATA [5] = 1;
            DATA [6] = 1;
            DATA [7] = 0;
            break;
        case '7':
            DATA [4] = 0;
            DATA [5] = 1;
            DATA [6] = 1;
            DATA [7] = 1;
            break;
        case '8':
            DATA [4] = 1;
            DATA [5] = 0;
            DATA [6] = 0;
            DATA [7] = 0;
            break;
        case '9':
            DATA [4] = 1;
            DATA [5] = 0;
            DATA [6] = 0;
            DATA [7] = 1;
            break;
        case 'A':
        case 'a':
            DATA [4] = 1;
            DATA [5] = 0;
            DATA [6] = 1;
            DATA [7] = 0;
            break;
        case 'B':
        case 'b':
            DATA [4] = 1;
            DATA [5] = 0;
            DATA [6] = 1;
            DATA [7] = 1;
            break;
        case 'C':
        case 'c':
            DATA [4] = 1;
            DATA [5] = 1;
            DATA [6] = 0;
            DATA [7] = 0;
            break;
        case 'D':
        case 'd':
            DATA [4] = 1;
            DATA [5] = 1;
            DATA [6] = 0;
            DATA [7] = 1;
            break;
        case 'E':
        case 'e':
            DATA [4] = 1;
            DATA [5] = 1;
            DATA [6] = 1;
            DATA [7] = 0;
            break;
        case 'F':
        case 'f':
            DATA [4] = 1;
            DATA [5] = 1;
            DATA [6] = 1;
            DATA [7] = 1;
            break;
        default:
break;      
        //    printf("\nInvalid hexadecimal digit %c",
          //         hexdec[0]);
        }
//   int main(int argc, char **argv)
//   {
   bcm2835_init();

   bcm2835_gpio_fsel(MOSI, BCM2835_GPIO_FSEL_OUTP);
   bcm2835_gpio_fsel(SCK, BCM2835_GPIO_FSEL_OUTP);
    bcm2835_gpio_fsel(SS_CS, BCM2835_GPIO_FSEL_OUTP);
          
         
           for(int i = 0; i < 8; i++) {
            
                              bcm2835_gpio_write(MOSI, DATA);//bcm2835_delayMicroseconds(1);                                                   
                              bcm2835_gpio_write(SCK, HIGH);//SCK UP
                              
                              //bcm2835_gpio_write(MOSI, DATA);                     
                              bcm2835_delayMicroseconds(1);
                              bcm2835_gpio_write(SCK, LOW);//SCK DOWN
                              }
           

                              bcm2835_gpio_write(MOSI, LOW);//defaul helyzet
      bcm2835_close();
}

void ENABLE_H ()
{
   bcm2835_init();

    bcm2835_gpio_fsel(SS_CS, BCM2835_GPIO_FSEL_OUTP);
   bcm2835_gpio_write(SS_CS, HIGH);
      bcm2835_close();

}

void ENABLE_L ()
{
   bcm2835_init();

    bcm2835_gpio_fsel(SS_CS, BCM2835_GPIO_FSEL_OUTP);
   bcm2835_gpio_write(SS_CS, LOW);
      bcm2835_close();   
}

void CD_H ()
{
   bcm2835_init();

    bcm2835_gpio_fsel(CD, BCM2835_GPIO_FSEL_OUTP);
   bcm2835_gpio_write(CD, HIGH);
      bcm2835_close();   
}

void CD_L ()
{
   bcm2835_init();

    bcm2835_gpio_fsel(CD, BCM2835_GPIO_FSEL_OUTP);
   bcm2835_gpio_write(CD, LOW);
      bcm2835_close();   
}



int main()
{    
   DEF (); // all out to 0
   ENABLE_H ();// if starts it the currect pos


   
   ENABLE_L ();
   CD_L ();
   SPI8 ("AE") ;
   SPI8 ("DC") ;
   SPI8 ("00") ;
   SPI8 ("81") ;
   SPI8 ("2F") ;
   SPI8 ("20") ;
   SPI8 ("A0") ;
   SPI8 ("C0") ;
   SPI8 ("A8") ;
   SPI8 ("7F") ;
   SPI8 ("D5") ;
   SPI8 ("50") ;
   SPI8 ("D9") ;
   SPI8 ("22") ;
   SPI8 ("DB") ;
   SPI8 ("35") ;
   SPI8 ("B0") ;
   SPI8 ("DA") ;
   SPI8 ("12") ;
   SPI8 ("A4") ;
   SPI8 ("A6") ;
   
   ENABLE_H ();
   bcm2835_delay(1);
   CD_L ();
   // SCR INI KÉSZ
   
   /// one page data  --------------------------------------00
   ENABLE_L ();
   SPI8 ("10") ;
   SPI8 ("00") ;
   SPI8 ("B0") ;
   CD_H ();
   for(int J = 0; J < 128; J++)
   {
   SPI8 ("FF") ;   
   }
   CD_L ();
   ENABLE_H ();
   
   /// one page data  --------------------------------------01
   ENABLE_L ();
   SPI8 ("10") ;
   SPI8 ("00") ;
   SPI8 ("B1") ;
   CD_H ();
   for(int J = 0; J < 128; J++)
   {
   SPI8 ("00") ;   
   }
   CD_L ();
   ENABLE_H ();
   
   /// one page data  --------------------------------------02
   ENABLE_L ();
   SPI8 ("10") ;
   SPI8 ("00") ;
   SPI8 ("B2") ;
   CD_H ();
   for(int J = 0; J < 128; J++)
   {
   SPI8 ("FF") ;   
   }
   CD_L ();
   ENABLE_H ();
   
   /// one page data  --------------------------------------03
   ENABLE_L ();
   SPI8 ("10") ;
   SPI8 ("00") ;
   SPI8 ("B3") ;
   CD_H ();
   for(int J = 0; J < 128; J++)
   {
   SPI8 ("FF") ;   
   }
   CD_L ();
   ENABLE_H ();
   
   /// one page data  --------------------------------------04
   ENABLE_L ();
   SPI8 ("10") ;
   SPI8 ("00") ;
   SPI8 ("B4") ;
   CD_H ();
   for(int J = 0; J < 128; J++)
   {
   SPI8 ("FF") ;   
   }
   CD_L ();
   ENABLE_H ();


   
   /// one page data  --------------------------------------05
   ENABLE_L ();
   SPI8 ("10") ;
   SPI8 ("00") ;
   SPI8 ("B5") ;
   CD_H ();
   for(int J = 0; J < 128; J++)
   {
   SPI8 ("FF") ;   
   }
   CD_L ();
   ENABLE_H ();


   
   /// one page data  --------------------------------------06
   ENABLE_L ();
   SPI8 ("10") ;
   SPI8 ("00") ;
   SPI8 ("B6") ;
   CD_H ();
   for(int J = 0; J < 128; J++)
   {
   SPI8 ("FF") ;   
   }
   CD_L ();
   ENABLE_H ();


   
   /// one page data  --------------------------------------07
   ENABLE_L ();
   SPI8 ("10") ;
   SPI8 ("00") ;
   SPI8 ("B7") ;
   CD_H ();
   for(int J = 0; J < 128; J++)
   {
   SPI8 ("FF") ;   
   }
   CD_L ();
   ENABLE_H ();


   
   /// one page data  --------------------------------------08
   ENABLE_L ();
   SPI8 ("10") ;
   SPI8 ("00") ;
   SPI8 ("B8") ;
   CD_H ();
   for(int J = 0; J < 128; J++)
   {
   SPI8 ("FF") ;   
   }
   CD_L ();
   ENABLE_H ();


   
   /// one page data  --------------------------------------09
   ENABLE_L ();
   SPI8 ("10") ;
   SPI8 ("00") ;
   SPI8 ("B9") ;
   CD_H ();
   for(int J = 0; J < 128; J++)
   {
   SPI8 ("FF") ;   
   }
   CD_L ();
   ENABLE_H ();


   
   /// one page data  --------------------------------------10
   ENABLE_L ();
   SPI8 ("10") ;
   SPI8 ("00") ;
   SPI8 ("BA") ;
   CD_H ();
   for(int J = 0; J < 128; J++)
   {
   SPI8 ("FF") ;   
   }
   CD_L ();
   ENABLE_H ();


   
   /// one page data  --------------------------------------11
   ENABLE_L ();
   SPI8 ("10") ;
   SPI8 ("00") ;
   SPI8 ("BB") ;
   CD_H ();
   for(int J = 0; J < 128; J++)
   {
   SPI8 ("FF") ;   
   }
   CD_L ();
   ENABLE_H ();


   
   /// one page data  --------------------------------------12
   ENABLE_L ();
   SPI8 ("10") ;
   SPI8 ("00") ;
   SPI8 ("BC") ;
   CD_H ();
   for(int J = 0; J < 128; J++)
   {
   SPI8 ("FF") ;   
   }
   CD_L ();
   ENABLE_H ();


   
   /// one page data  --------------------------------------13
   ENABLE_L ();
   SPI8 ("10") ;
   SPI8 ("00") ;
   SPI8 ("BD") ;
   CD_H ();
   for(int J = 0; J < 128; J++)
   {
   SPI8 ("FF") ;   
   }
   CD_L ();
   ENABLE_H ();


   
   /// one page data  --------------------------------------14
   ENABLE_L ();
   SPI8 ("10") ;
   SPI8 ("00") ;
   SPI8 ("BE") ;
   CD_H ();
   for(int J = 0; J < 128; J++)
   {
   SPI8 ("FF") ;   
   }
   CD_L ();
   ENABLE_H ();


   
   /// one page data  --------------------------------------15
   ENABLE_L ();
   SPI8 ("10") ;
   SPI8 ("00") ;
   SPI8 ("BF") ;
   CD_H ();
   for(int J = 0; J < 128; J++)
   {
   SPI8 ("FF") ;   
   }
   CD_L ();
   ENABLE_H ();
   
   
   //display on
   CD_L ();
   ENABLE_L ();
   SPI8 ("AF") ;
   ENABLE_H ();
   CD_L ();
   
   //display on
   CD_L ();
   ENABLE_L ();
   SPI8 ("AF") ;
   ENABLE_H ();
   CD_L ();
   
   
   /// data
   ENABLE_L ();
   SPI8 ("15") ;
   SPI8 ("08") ;
   SPI8 ("B0") ;
   CD_H ();
   for(int J = 0; J < 128; J++)
   {
   SPI8 ("FF") ;   
   }
   CD_L ();
   ENABLE_H ();
   
      /// data
   ENABLE_L ();
   SPI8 ("10") ;
   SPI8 ("00") ;
   SPI8 ("B1") ;
   CD_H ();
   for(int J = 0; J < 128; J++)
   {
   SPI8 ("FF") ;   
   }
   CD_L ();
   ENABLE_H ();
   
   
   
}//main END---------------------------------------------------
Title: Re: RASPBERRY PI C
Post by: hamster_nz on September 11, 2020, 10:12:50 pm
Hi! I'm quite happy to help. I'll have a look over your code.. 

I'm not sure what your question is though!

I have a Raspberry Pi (well, quite a few actually..), but not that model of display, so although I can build it I can't test if it works or not.

Mike
Title: Re: RASPBERRY PI C
Post by: hamster_nz on September 11, 2020, 11:16:08 pm
So I've tidied up the code a bit:

- Made the ASCII hex to value code a lot shorter

- Removed a lot of the repeated code into functions

I've found a bit of inconsistency - have a look at for the WHY IS THIS "00" comment towards the end.

I also think you should call bcm2835_init(); only once, but you seem to be calling it every time you send a byte,...

Code: [Select]
#include <stdio.h>
#include "bcm2835.h"

// bcm2835_delayMicroseconds()
// Blinks on RPi Plug P1 pin 11 (which is GPIO pin 17)
#define MOSI RPI_GPIO_P1_19   // MOSI DATA 8 bit
#define SCK RPI_GPIO_P1_23    // SCK Clock
#define SS_CS RPI_GPIO_P1_24  // CS Slave slect
#define CD RPI_GPIO_P1_21     // CD command select MISO

void DEF ()
{
   bcm2835_init();
   
   bcm2835_gpio_fsel(CD, BCM2835_GPIO_FSEL_OUTP);
   bcm2835_gpio_fsel(SS_CS, BCM2835_GPIO_FSEL_OUTP);
   bcm2835_gpio_fsel(MOSI, BCM2835_GPIO_FSEL_OUTP);
   bcm2835_gpio_fsel(SCK, BCM2835_GPIO_FSEL_OUTP);
 
   bcm2835_gpio_write(CD, LOW);
   bcm2835_gpio_write(SS_CS, LOW);
   bcm2835_gpio_write(MOSI, LOW);
   bcm2835_gpio_write(SCK, LOW);
   bcm2835_close();
}


void SPI8(char* hexdec)
{
  int value, i;
  int DATA [8]; //8 biten megy a kommmunikáció

  fprintf(stderr,"Sending %s",hexdec);

  if(hexdec[0] >= '0' && hexdec[0] <= '9') {
    value = hexdec[0] - '0';
  } else if(hexdec[0] >= 'A' && hexdec[0] <= 'Z') {
    value = hexdec[0] - 'A' + 10;
  } else if(hexdec[0] >= 'a' && hexdec[0] <= 'z') {
    value = hexdec[0] - 'a' + 10;
  } else {
    fprintf(stderr,"Bad hexdec[0]\n");
    return;
  }
  value *= 16;
  if(hexdec[1] >= '0' && hexdec[1] <= '9') {
    value += hexdec[1] - '0';
  } else if(hexdec[1] >= 'A' && hexdec[1] <= 'Z') {
    value += hexdec[1] - 'A' + 10;
  } else if(hexdec[1] >= 'a' && hexdec[1] <= 'z') {
    value += hexdec[1] - 'a' + 10;
  } else {
    fprintf(stderr,"Bad hexdec[1]\n");
    return;
  }

  for(i=0; i < 8; i++) {
    DATA[i] = (value & (1<<i)) ? 1 : 0;
  }
 
  bcm2835_init();
  bcm2835_gpio_fsel(MOSI, BCM2835_GPIO_FSEL_OUTP);
  bcm2835_gpio_fsel(SCK, BCM2835_GPIO_FSEL_OUTP);
  bcm2835_gpio_fsel(SS_CS, BCM2835_GPIO_FSEL_OUTP);
         
  for(int i = 0; i < 8; i++) {
    bcm2835_gpio_write(MOSI, DATA[i]); //bcm2835_delayMicroseconds(1);                                                   
    bcm2835_gpio_write(SCK, HIGH);  //SCK UP
    bcm2835_delayMicroseconds(1);
    bcm2835_gpio_write(SCK, LOW);  //SCK DOWN
  }
  bcm2835_gpio_write(MOSI, LOW);//defaul helyzet
  bcm2835_close();
}

void ENABLE_H ()
{
  bcm2835_init();
  bcm2835_gpio_fsel(SS_CS, BCM2835_GPIO_FSEL_OUTP);
  bcm2835_gpio_write(SS_CS, HIGH);
  bcm2835_close();
}

void ENABLE_L ()
{
   bcm2835_init();
   bcm2835_gpio_fsel(SS_CS, BCM2835_GPIO_FSEL_OUTP);
   bcm2835_gpio_write(SS_CS, LOW);
   bcm2835_close();   
}

void CD_H ()
{
   bcm2835_init();
   bcm2835_gpio_fsel(CD, BCM2835_GPIO_FSEL_OUTP);
   bcm2835_gpio_write(CD, HIGH);
   bcm2835_close();   
}

void CD_L ()
{
  bcm2835_init();
  bcm2835_gpio_fsel(CD, BCM2835_GPIO_FSEL_OUTP);
  bcm2835_gpio_write(CD, LOW);
  bcm2835_close();   
}


void send_data_block(char *a, char *b, char *c, char *d) {
   ENABLE_L ();
   SPI8 (a) ;
   SPI8 (b) ;
   SPI8 (c) ;
   CD_H ();

   // An idle pattern to waste some time????
   for(int i = 0; i < 128; i++) {
     SPI8 (d) ;   
   }
   CD_L ();
   ENABLE_H ();
}

void display_on(void) {
   CD_L ();
   ENABLE_L ();
   SPI8 ("AF") ;
   ENABLE_H ();
   CD_L ();
}

int main()
{   
   DEF (); // all out to 0
   ENABLE_H ();// if starts it the currect pos
   ENABLE_L ();
   CD_L ();
   SPI8 ("AE") ;
   SPI8 ("DC") ;
   SPI8 ("00") ;
   SPI8 ("81") ;
   SPI8 ("2F") ;
   SPI8 ("20") ;
   SPI8 ("A0") ;
   SPI8 ("C0") ;
   SPI8 ("A8") ;
   SPI8 ("7F") ;
   SPI8 ("D5") ;
   SPI8 ("50") ;
   SPI8 ("D9") ;
   SPI8 ("22") ;
   SPI8 ("DB") ;
   SPI8 ("35") ;
   SPI8 ("B0") ;
   SPI8 ("DA") ;
   SPI8 ("12") ;
   SPI8 ("A4") ;
   SPI8 ("A6") ;
   
   ENABLE_H ();
   bcm2835_delay(1);
   CD_L ();

   // SCR INI KÉSZ
   send_data_block("10","00","B0","FF");
   send_data_block("10","00","B1","00"); // << WHY IS THIS "00"?
   send_data_block("10","00","B2","FF");
   send_data_block("10","00","B3","FF");
   send_data_block("10","00","B4","FF");
   send_data_block("10","00","B5","FF");
   send_data_block("10","00","B6","FF");
   send_data_block("10","00","B7","FF");
   send_data_block("10","00","B8","FF");
   send_data_block("10","00","B9","FF");
   send_data_block("10","00","BA","FF");
   send_data_block("10","00","BB","FF");
   send_data_block("10","00","BC","FF");
   send_data_block("10","00","BD","FF");
   send_data_block("10","00","BE","FF");
   send_data_block("10","00","BF","FF");
   display_on();
   display_on();
   
   /// data
   send_data_block("15","08","B0","FF");
   send_data_block("10","00","B1","FF");
}
Title: Re: RASPBERRY PI C
Post by: greenpossum on September 11, 2020, 11:51:13 pm
Much better than the original, but why send in strings of the hex value, why not just pass in the hex value directly, i.e.

Code: [Select]
SPI8(0xAE);

then you don't have to parse anything.
Title: Re: RASPBERRY PI C
Post by: hamster_nz on September 11, 2020, 11:56:35 pm
Much better than the original, but why send in strings of the hex value, why not just pass in the hex value directly, i.e.

Code: [Select]
SPI8(0xAE);

then you don't have to parse anything.

I was thinking that, but then I started to see the OPs intent. From their perspective, it would be nicer (but less efficient) to do something like

Code: [Select]
   DEF (); // all out to 0
   SET_ENABLE(HIGH);// if starts it the currect pos
   SET_ENABLE(LOW);
   SET_CD(LOW);
   send_data_block("AE DC 00 81 2F 20 A0 C0 A8 7F D5 50 D9 22 DB 35 B0 DA 12 A4 A6") ;
   SET_ENABLE(HIGH);
   bcm2835_delay(1);
   SET_CD(LOW);

   // SCR INI KÉSZ
   send_data_block("10 00 B0");
   send_data_block("10 00 B1");
   send_data_block("10 00 B2");
   send_data_block("10 00 B3");
   send_data_block("10 00 B4");

Well, at least until the display is functioning correctly.
Title: Re: RASPBERRY PI C
Post by: TK on September 12, 2020, 12:01:51 am
Much better than the original, but why send in strings of the hex value, why not just pass in the hex value directly, i.e.

Code: [Select]
SPI8(0xAE);

then you don't have to parse anything.
If you pass an hex value, OP needs to change the bit banging loop to do bit manipulation.  Also function call is expensive, it is better to write a new function where you can pass an array of bytes and the number of bytes to transfer and do it in a single function call instead of calling SPI8() all the time.
Title: Re: RASPBERRY PI C
Post by: greenpossum on September 12, 2020, 12:03:02 am
In the second case the only difference between calls is one byte so just write a wrapper around SPI8() to call it with 0x10 0x00 then the desired byte, and any postamble. Make it inline if you are worried about the overhead of the function call but this is probably small compared to the body of the function.

In the first case, just wrap a loop that calls SPI8() over an array of bytes, using sizeof() to get the length of the array. If you are worried about the function call overhead, then write a variant of SPI8 for an array of bytes so that the loop is inside the function.

Bit extraction from a byte is done all the time, it's just a shift and mask in a loop. You have do it anyway if you pass in a string, the point is changing to a binary argument removes the hex parsing which is done for every call. I'm talking about the improved version by hamster_nz, not the horrible version by OP.
Title: Re: RASPBERRY PI C
Post by: hamster_nz on September 12, 2020, 12:28:27 am
I can see where the OP was coming from... here it is again with slightly more refactoring, and I think it's almost in good enough shape to test.

I keep on reposting the code so the OP can see it evolve.

Code: [Select]
#include <stdio.h>
#include "bcm2835.h"

#define MOSI RPI_GPIO_P1_19   // MOSI DATA 8 bit
#define SCK RPI_GPIO_P1_23    // SCK Clock
#define SS_CS RPI_GPIO_P1_24  // CS Slave select
#define CD RPI_GPIO_P1_21     // CD command select MISO

void DEF ()
{
   // Set pins to output
   bcm2835_gpio_fsel(CD,    BCM2835_GPIO_FSEL_OUTP);
   bcm2835_gpio_fsel(SS_CS, BCM2835_GPIO_FSEL_OUTP);
   bcm2835_gpio_fsel(MOSI,  BCM2835_GPIO_FSEL_OUTP);
   bcm2835_gpio_fsel(SCK,   BCM2835_GPIO_FSEL_OUTP);
   // Set inital state
   bcm2835_gpio_write(CD,    LOW);
   bcm2835_gpio_write(SS_CS, LOW);
   bcm2835_gpio_write(MOSI,  LOW);
   bcm2835_gpio_write(SCK,   LOW);
}

int hexchar_to_value(char c) {
  if(c >= '0' && c <= '9') return c - '0';
  if(c >= 'A' && c <= 'Z') return c - 'A' + 10;
  if(c >= 'a' && c <= 'z') return c - 'a' + 10;
  return -1;
}

int SPI8(char* hexdec)
{
  int value, digit1, digit2, i;
  int DATA [8]; //8 biten megy a kommmunikáció

  digit1 = hexchar_to_value(hexdec[0]);
  if(digit1 < 0) {
    fprintf(stderr,"Bad hex digit\n");
    return 0;
  }

  digit2 = hexchar_to_value(hexdec[1]);
  if(digit2 < 0) {
    fprintf(stderr,"Bad hex digit\n");
    return 0;
  }

  value = digit1*16+digit2;

  fprintf(stderr,"Sending %02X\n",value);
  for(i=0; i < 8; i++) {
    DATA[i] = (value & (1<<i)) ? 1 : 0;
  }
 
  bcm2835_gpio_fsel(MOSI, BCM2835_GPIO_FSEL_OUTP);
  bcm2835_gpio_fsel(SCK, BCM2835_GPIO_FSEL_OUTP);
  bcm2835_gpio_fsel(SS_CS, BCM2835_GPIO_FSEL_OUTP);
         
  for(int i = 0; i < 8; i++) {
    bcm2835_gpio_write(MOSI, DATA[i]); //bcm2835_delayMicroseconds(1);                                                   
    bcm2835_gpio_write(SCK, HIGH);  //SCK UP
    bcm2835_delayMicroseconds(1);
    bcm2835_gpio_write(SCK, LOW);  //SCK DOWN
  }
  bcm2835_gpio_write(MOSI, LOW);//defaul helyzet
  return 1;
}

void SET_ENABLE (int state)
{
  bcm2835_gpio_fsel(SS_CS, BCM2835_GPIO_FSEL_OUTP);
  bcm2835_gpio_write(SS_CS, state);
  fprintf(stderr,"Setting ENABLE to %s\n",state ? "HIGH": "LOW");
}

void SET_CD (int state)
{
  bcm2835_gpio_fsel(CD, BCM2835_GPIO_FSEL_OUTP);
  bcm2835_gpio_write(CD, state);
  fprintf(stderr,"Setting CD to %s\n",state ? "HIGH": "LOW");
}

void send_data_block(char *data) {
   // 'data' is a string of hexadecimal bytes e.g. "12 34 AB CD"
   SET_ENABLE(LOW);
   // While we are not at the end of the string, send data
   while(data[0] != '\0') {
      int rtn = SPI8 (data);  // Send the data
      if(!rtn) // If the send failed the drop out of loop
         break;

      data += 2;    // Skip forward two characters

      // Eat any spaces
      while(data[0] == ' ') {
        data++;
      }
   }
   SET_CD(HIGH);

   // An idle pattern to waste some time????
   for(int i = 0; i < 128; i++) {
     SPI8 ("FF") ;   
   }
   SET_CD(LOW);
   SET_ENABLE(HIGH);
}

void display_on(void) {
   SET_CD(LOW);
   SET_ENABLE(LOW);
   SPI8 ("AF") ;
   SET_ENABLE(HIGH);
   SET_CD(LOW);
}

int main()
{   
   bcm2835_init();

   DEF (); // all out to 0
   SET_ENABLE(HIGH);// if starts it the currect pos
   SET_ENABLE(LOW);
   SET_CD(LOW);
   send_data_block("AE DC 00 81 2F 20 A0 C0 A8 7F D5 50 D9 22 DB 35 B0 DA 12 A4 A6") ;
   SET_ENABLE(HIGH);
   bcm2835_delay(1);
   SET_CD(LOW);

   // SCR INI KÉSZ
   send_data_block("10 00 B0");
   send_data_block("10 00 B1");
   send_data_block("10 00 B2");
   send_data_block("10 00 B3");
   send_data_block("10 00 B4");
   send_data_block("10 00 B5");
   send_data_block("10 00 B6");
   send_data_block("10 00 B7");
   send_data_block("10 00 B8");
   send_data_block("10 00 B9");
   send_data_block("10 00 BA");
   send_data_block("10 00 BB");
   send_data_block("10 00 BC");
   send_data_block("10 00 BD");
   send_data_block("10 00 BE");
   send_data_block("10 00 BF");

   display_on();
   display_on();
   
   send_data_block("15 08 B0");
   send_data_block("10 00 B1");

   bcm2835_close();
}
Title: Re: RASPBERRY PI C
Post by: greenpossum on September 12, 2020, 12:55:02 am
You can fold the extraction of the bit into the bit banging loop and avoid the local array DATA.

Code: [Select]
DATA[i] = (value & (1<<i)) ? 1 : 0;
Title: Re: RASPBERRY PI C
Post by: hamster_nz on September 12, 2020, 03:51:33 am
Had a few more minutes to play.

- Added check that library initialised OK (make sure that you run it as 'root' with sudo)

- Fixed up flapping MOSI

- Set default state of MOSI correct

- Fixed up the initial state of the CS and ENABLE pins

- Got rid of excess calls setting pins to output mode

- Connected Raspberry to Logic Analyser and traced (although didn't configure protocol analyser to check bit ordering and so on)

- Made SCLK more symmetrical (just because it bugged me)

At a glance it looks as if it should work... will add a snapshot from the Logic Analyser later today.

Code: [Select]
#include <stdio.h>
#include <unistd.h>
#include "bcm2835.h"

#define MOSI  RPI_GPIO_P1_19  // MOSI DATA 8 bit
#define CD    RPI_GPIO_P1_21  // CD command select MISO
#define SCK   RPI_GPIO_P1_23  // SCK Clock
#define SS_CS RPI_GPIO_P1_24  // CS Slave slect

static int verbose = 0;

static void DEF () {
   // Set inital state of pins
   bcm2835_gpio_write(CD,    HIGH);
   bcm2835_gpio_write(SS_CS, HIGH);
   bcm2835_gpio_write(MOSI,  LOW);
   bcm2835_gpio_write(SCK,   LOW);

   // Set pins to output
   bcm2835_gpio_fsel(CD,    BCM2835_GPIO_FSEL_OUTP);
   bcm2835_gpio_fsel(SS_CS, BCM2835_GPIO_FSEL_OUTP);
   bcm2835_gpio_fsel(MOSI,  BCM2835_GPIO_FSEL_OUTP);
   bcm2835_gpio_fsel(SCK,   BCM2835_GPIO_FSEL_OUTP);
}

static int hexchar_to_value(char c) {
  if(c >= '0' && c <= '9') return c - '0';
  if(c >= 'A' && c <= 'Z') return c - 'A' + 10;
  if(c >= 'a' && c <= 'z') return c - 'a' + 10;
  return -1;
}

static int SPI8(char* hexdec) {
  int value, digit1, digit2, i;
  int DATA [8]; //8 biten megy a kommmunikáció

  digit1 = hexchar_to_value(hexdec[0]);
  if(digit1 < 0) {
    fprintf(stderr,"Bad hex digit\n");
    return 0; // false
  }

  digit2 = hexchar_to_value(hexdec[1]);
  if(digit2 < 0) {
    fprintf(stderr,"Bad hex digit\n");
    return 0; // false
  }

  value = digit1*16 + digit2;

  if(verbose) fprintf(stderr,"Sending %02X\n",value);

  for(i=0; i < 8; i++) {
    DATA[i] = (value & (1<<i)) ? 1 : 0;
  }
         
  for(int i = 0; i < 8; i++) {
    bcm2835_gpio_write(MOSI, DATA[i] ? HIGH : LOW); //bcm2835_delayMicroseconds(1);                                                   
    bcm2835_delayMicroseconds(1);
    bcm2835_gpio_write(SCK, HIGH);     //SCK UP

    bcm2835_gpio_write(MOSI, DATA[i] ? HIGH : LOW); //bcm2835_delayMicroseconds(1);                                                   
    bcm2835_delayMicroseconds(1);
    bcm2835_gpio_write(SCK, LOW);      //SCK DOWN
  }
  return 1; // true
}

void SET_ENABLE (int state) {
  if(verbose) fprintf(stderr,"Setting ENABLE to %s\n",state ? "HIGH": "LOW");
  bcm2835_gpio_write(SS_CS, state);
}

void SET_CD (int state) {
  if(verbose) fprintf(stderr,"Setting CD to %s\n",state ? "HIGH": "LOW");
  bcm2835_gpio_write(CD, state);
}

void send_data_block(char *data) { // 'data' is a string of hexadecimal bytes e.g. "12 34 AB CD"
   SET_CD(LOW);
   SET_ENABLE(LOW);
   // While we are not at the end of the string
   while(data[0] != '\0') {
      int rtn = SPI8 (data);  // Send the data

      if(!rtn) // If the send failed the drop out of loop
         break;

      data += 2;    // Skip forward two characters

      // Eat any spaces
      while(data[0] == ' ') {
        data++;
      }
   }
   // The last byte might have left MOSI high, so set it low
   bcm2835_gpio_write(MOSI, LOW);       //defaul helyzet
   SET_CD(HIGH);

   // An idle pattern to waste some time????
   for(int i = 0; i < 128; i++) {
     SPI8 ("00") ;   
   }
   SET_ENABLE(HIGH); // Keep MOSI LOW
}

void display_on(void) {
   send_data_block("AF");
}

int main() {   
   if(!bcm2835_init()) {
     fprintf(stderr,"Unable to initialize BCM2835 library\n");
     return 0;
   }

   DEF (); // all out to 0

   SET_ENABLE(HIGH);// if starts it the currect pos
   send_data_block("AE DC 00 81 2F 20 A0 C0 A8 7F D5 50 D9 22 DB 35 B0 DA 12 A4 A6") ;
   bcm2835_delay(1);

   // SCR INI KÉSZ
   send_data_block("10 00 B0");
   send_data_block("10 00 B1");
   send_data_block("10 00 B2");
   send_data_block("10 00 B3");
   send_data_block("10 00 B4");
   send_data_block("10 00 B5");
   send_data_block("10 00 B6");
   send_data_block("10 00 B7");
   send_data_block("10 00 B8");
   send_data_block("10 00 B9");
   send_data_block("10 00 BA");
   send_data_block("10 00 BB");
   send_data_block("10 00 BC");
   send_data_block("10 00 BD");
   send_data_block("10 00 BE");
   send_data_block("10 00 BF");

   display_on();
   display_on();
   
   /// data
   send_data_block("15 08 B0");
   send_data_block("10 00 B1");

   sleep(1); 
   bcm2835_close();
}
Title: Re: RASPBERRY PI C
Post by: hamster_nz on September 12, 2020, 08:13:14 am
I set up a protocol decoder... here's the first write. The -on-the-wire bit order is back to front!

So

Code: [Select]
  ...    
  for(int i = 0; i < 8; i++) {
    bcm2835_gpio_write(MOSI, DATA[i] ? HIGH : LOW); //bcm2835_delayMicroseconds(1);                                                   
    bcm2835_delayMicroseconds(1);
    ...

Should be

Code: [Select]
  ...    
  for(int i = 7; i >= 0; i--) {
    bcm2835_gpio_write(MOSI, DATA[i] ? HIGH : LOW); //bcm2835_delayMicroseconds(1);                                                   
    bcm2835_delayMicroseconds(1);
    ...
Title: Re: RASPBERRY PI C
Post by: hamster_nz on September 12, 2020, 10:57:58 am
With that change it now decodes correctly - see attached image.

However, I worry that it won't work correctly first time after a reboot, because the pins power up in an non-helpful state.

If it only works consistently when it's run for a second time, then sending a dummy command before the true initialization string should fix it.
Title: Re: RASPBERRY PI C
Post by: greenpossum on September 12, 2020, 11:07:37 am
Code: [Select]
for(int i = 7; i >= 0; i--) {
    bcm2835_gpio_write(MOSI, DATA[i] ? HIGH : LOW); //bcm2835_delayMicroseconds(1);                                                   
    bcm2835_delayMicroseconds(1);
    ...

That code can be optimised a lot. You can get rid of the counter and let the bit mask double as the counter like this:

Code: [Select]
for(unsigned int mask = 0x80; mask != 0; mask >>=1) {
    bcm2835_gpio_write(MOSI, (value & mask) ? HIGH : LOW); //bcm2835_delayMicroseconds(1);                                                   
    bcm2835_delayMicroseconds(1);
    ...

And of course by working on value directly you don't need the preceding loop and array DATA.
Title: Re: RASPBERRY PI C
Post by: hamster_nz on September 13, 2020, 05:51:08 am
I wonder where the oeiginal poster is?

.... Tumbleweed....

Glad I didn't spend my spare time polishing up and testing their code rather than my own stuff.

Oh wait.....
Title: Re: RASPBERRY PI C
Post by: maginnovision on September 13, 2020, 03:31:01 pm
Don't worry I'm sure he learned(ctrl+c) and applied those lessons(ctrl+v).
Title: Re: RASPBERRY PI C
Post by: Monkeh on September 13, 2020, 03:32:26 pm
Congratulations, you just did his homework for him. :-DD