-
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.
-
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---------------------------------------------------
-
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
-
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,...
#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");
}
-
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.
SPI8(0xAE);
then you don't have to parse anything.
-
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.
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
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.
-
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.
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.
-
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.
-
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.
#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();
}
-
You can fold the extraction of the bit into the bit banging loop and avoid the local array DATA.
DATA[i] = (value & (1<<i)) ? 1 : 0;
-
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.
#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();
}
-
I set up a protocol decoder... here's the first write. The -on-the-wire bit order is back to front!
So
...
for(int i = 0; i < 8; i++) {
bcm2835_gpio_write(MOSI, DATA[i] ? HIGH : LOW); //bcm2835_delayMicroseconds(1);
bcm2835_delayMicroseconds(1);
...
Should be
...
for(int i = 7; i >= 0; i--) {
bcm2835_gpio_write(MOSI, DATA[i] ? HIGH : LOW); //bcm2835_delayMicroseconds(1);
bcm2835_delayMicroseconds(1);
...
-
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.
-
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:
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.
-
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.....
-
Don't worry I'm sure he learned(ctrl+c) and applied those lessons(ctrl+v).
-
Congratulations, you just did his homework for him. :-DD