Digole UART/I2C/SPI Display Library

It's due to the I2C system not sending data until 'endTramsmission' is called. Once I finish my re-write of the I2C system this won't be an issue, but for now we have to delay after each I2C call. Sending text and any other command to the display is still basically instant, it just really slows down the transfer of large color bitmaps over I2C.

Basically this! :smiley:

Almost there guys, just working on the SS toggling code and we’ll basically be ready! :smiley:

1 Like

Man, this CS issue is killing me. If I hook the OLED’s CS pin to the Core it just doesn’t work correctly. I’ve tried toggling the CS pin before the SPI.transfer statement, I’ve tried toggling it in the main code before calling the display function and nothing works. I just get a corrupt line or something drawn on the screen. However, if I tie CS straight to ground it works fine. I’ve tried both digitalWrite and direct port manipulation, plus adding delays.

Fear not, I’ve got my logic out and I’m working it!

2 Likes

Standing by, if you need some help tracking it down let me know… I have my display wired up, and a custom image generated :slight_smile:

Will do, I’m going to grab some test data with the Logic real quick and try a couple more tricks,

If that doesn’t work I’ll send you some test code. Have you used Digole’s Image to C Array Tool on your custom image? What size is it and did you convert it in 256 Color or 262K Color modes? Finally, how much longer are you going to be around tonight?

Yep, I converted a 160 x 128 png with that tool to DEC format and stuck it all in a const uint8_t digole256[20480] = { 23,27,27,27,27,27,27,27,23,14,10,9, etc..}; it’s big… seems too big, but I’m pretty confident this will be in Flash memory so I’m not worried.

I’ll be around till at least 12pm CST

That looks good except you should change your array like this: const unsigned char digole256[] = { 23,27,27,27,27,27,27,27,23,14,10,9, etc.. };

It does seem large, but it only takes up 20KB which still leaves a lot of space on the flash! It’s the 262K Color images that are too big for the onboard flash. I’ve found the biggest I can go is around 120x92. My plan is to add a function to display bitmaps compressed with Run Length Encoding, which should drastically decrease the space needed without sacrificing speed. I’d like to expand that to some sort of Golomb Entropy Encoding or a Burrows-Wheeler compression, possibly on top of the RLE (depending on how I implement it). Depending on the image this should let us losslessly bring a 60KB 262K Color Bitmap down to 6KB.

unsigned char is the same as uint8_t so are you saying I shouldn’t define the size of the array? Seems to compile either way for the size argument.

Interesting thoughts on the compression… I’m guessing the highest fastest-to-decompress to compressed-size ratio will be the winner.

timb, all this compression talk is making me think you don’t get enough sleep!

I can help with the debugging but it will have to be in the morning. Good luck to both of you!

:smile:

Sorry, I'm in the habit of using unsigned char in C since it's 8-bits and can be read as a byte (yay for weak types). But obviously uint8_t is a single byte as well. Anyway, yeah, you don't need to define the size of the array; I guess you can if you want but it's just extra work figuring it out. When you make the drawBitmap call you have to define the size (height and width) of the bitmap, so it handles the math for you. :smiley:

Okay, so take a look at this:

Each of those blocks of data decodes just fine if I zoom in. The CS line is going low with plenty of buffer time. Can you see anything wrong with it?

Here's the code:

const byte CS = A0;
DigoleSerialDisp oled(CS);

void setup() {

//    PIN_MAP[CS].gpio_peripheral->BRR = PIN_MAP[CS].gpio_pin; //Low
//    PIN_MAP[CS].gpio_peripheral->BSRR = PIN_MAP[CS].gpio_pin; //High
    pinMode(CS, OUTPUT);
    PIN_MAP[CS].gpio_peripheral->BSRR = PIN_MAP[CS].gpio_pin; //High
    delay(1000);
    oled.begin();
    delay(100);
    PIN_MAP[CS].gpio_peripheral->BRR = PIN_MAP[CS].gpio_pin; //Low
    delay(100);
    oled.clearScreen();
    delay(100);
    PIN_MAP[CS].gpio_peripheral->BSRR = PIN_MAP[CS].gpio_pin; //High
    delay(100);
    PIN_MAP[CS].gpio_peripheral->BRR = PIN_MAP[CS].gpio_pin; //Low
    delay(100);
    oled.drawBitmap262K(20, 18, 120, 92, colorDemo);
    delay(100);
    PIN_MAP[CS].gpio_peripheral->BSRR = PIN_MAP[CS].gpio_pin; //High
    
}

@timb Just some quick feedback… you talk about CS and SS. They are one in the same right? Why not use SS as A2 since the SPI Class is already setting it to an output and setting it high. You obviously have to control it thereafter.

One other user found that when using a pin other than A2, it would only clock on the lower 3 bits of data (i.e. missing 5 clock transitions from bit 7 through bit 3. I have no idea why that would happen, and shouldn’t… but something to try.

Have you tried leaving the SS pin low from start to finish? Looking at the code I don’t see why it should matter though… typically you just have to wrap your transfers with SS low.

I know you said it’s working if you just ground the SS pin, which leads me to believe it needs to be low sooner than it is. See if getting it low before the SCLK goes high matters/helps.

Just checking, you are using MODE0 right? I know I know, it works when SS is grounded… hmm.

Probably doesn’t mattery MUCH, but all pins are defined as uint16_t … A0 actually equals 10 in decimal… again, probably doesn’t matter. #define CS A0 should work too.

Damn I think everyone in the world besides me has a Logic or Logic 16 -_- why not me?? hehehe

Yeah, CS and SS are both terms for Chip Select. We can use A2, but I'm using a separate pin just to verify everything is working right.

According to my Logic all the data is valid. Like I said in the last post, if I zoom in on those data blocks I can see the text commands (CL, EDIM3, etc.) plus…

It works if I tie CS low. Pulling it low before SCLK goes high is a good idea, let me try it.

MODE3, actually, which is the default SPI condition on the Spark Core anyway.

Look out for a private message shortly.

So my next step is to hook this to my Arduino and see how it works with their library. I'll report back shortly!

Digole's programming manual only says "rising edge" so try MODE0 as well (the other rising edge mode) just for good measure :wink:

http://wallike.com/wp-content/uploads/2013/06/Cute-Minions-Wallpaper-640x360.jpg

Yup, I had tried it earlier this evening and it flat out doesn't work. Like I said, it's working with the CS line tied low, so MODE3 is certainly the right way to go. :smile:

So it works just fine on the Arduino. I’m going to capture that with my Logic and compare the timing. An interesting thing I noticed about the stock Digole library is they’re using shiftOut instead of the hardware SPI to communicate with the display. The Core has shiftOut support in the library now, right? Is it software based or does it run off the SPI interface?

If it’s the former I could add a SoftSPI mode to the library so you could use it on a different pin set if needed. (That’s something for down the road, just a thought!)

I was looking for an arduino example to compare… couldn’t find one with SPI…

Yes shiftOut() is a straight up software banger:
https://github.com/spark/core-firmware/blob/master/src/spark_wiring.cpp#L541-L555

But you know as I do digitalWrite() is slow (2us)

Well this is interesting… Hooked to the Arduino using the stock Digole Library and it’s talking to the display using MODE0. But when I use MODE3 on the Spark Core it works fine.

By the way @BDub did you get my private message?

Try MODE0 :slight_smile: It looks like the only difference really between 3 and 0 is MODE3 is SLCK idle high, and MODE0 is SLCK idle low. SS does have to be low before you start to clock (i.e. transition away from idle state) so just by changing the mode it might be the fix.

Got it! Replied :smile:

Tried that and still no dice, but I think I just found the problem! More in a minute.

@timb this is so lame, but I feel empowered that I’ve cleared my welcome display! xD Time to sleep bro, I hung in there til 1:06am. Tomorrow will be like Xmas morning! :slight_smile:

uint16_t _Clockpin = A3;
uint16_t _Datapin = A5;
uint16_t _SSpin = A2;

size_t write(uint8_t value) {
    digitalWrite(_SSpin, LOW);
    digitalWrite(_SSpin, LOW);
    digitalWrite(_SSpin, LOW);
    shiftOut(_Datapin, _Clockpin, MSBFIRST, value);
    digitalWrite(_SSpin, HIGH);
    return 1; // assume sucess
}

size_t write_str(const String &s)
{
  size_t n = 0;
  for (uint16_t i = 0; i < s.length(); i++) {
    n += write(s[i]);
  }
  return n;
}

void setup() {
    pinMode(_Clockpin, OUTPUT);
    pinMode(_Datapin, OUTPUT);
    pinMode(_SSpin, OUTPUT);
    digitalWrite(_SSpin, HIGH);
    digitalWrite(_Clockpin, LOW);
    digitalWrite(_Datapin, LOW);
}

void loop() {
    write_str("CL");
    delay(5000);
}