STM32, Maple and Maple mini port to IDE 1.5.x

Victor, thanks for the comments. I think as long as you guys keep in mind that, while you're writing your libraries, that multiple devices should have unfettered access to the SPI buss, then you're ok. The Teensy ST7735 library code is really a mess in this regards. There are at least 3 major problems with the Teensy libraries, in regards SPI buss contention.

In any case - without getting too carried away --> It Works Now! I can talk to both ST7735 LCD and 23LC1024 SPI RAM chips now with the Teensy3.1 board.

You guys have been a big help. The past 2 days I've been looking at the Teensy SPI and ST7735 libraries, and trying to decipher the 50-page section on SPI in the d/s. As luck would have it, Ray posted about his o'scope project today, and I took a look at that. Turns out the ILI9341 LCD code for the STM32 is almost identical to the ST7735 LCD code for the Teensy, other than different register setups for the graphics chips, and except for the radical customizations the Teensy guy did.

So, using the STM32 ILI9341 SPI control code as a template, I rebuilt the Teensy ST7735 library, and the darn thing works the first time I try it. Foo. Now, I can put the OV7670 camera system all back together, and see how it goes. The LCD updates are a bit slower now, but I can work on that, now that the darn thing works at all, :-).

One thing I did discover, and possibly the STM32 chip registers are similar, is the Teensy code sends data to the SPI buss using the following command:

SPI0.PUSHR = c | (pcs_command << 16) | SPI_PUSHR_CTAS(0);

Here, c is the databyte, and variable pcs_command contains a mask to the CS bits to be automatically toggled, in this case both CS and DC. From the d/s:

21–16 PCS[5:0]  Select which PCS signals are to be asserted for the transfer. Refer to the chip configuration chapter for the number of PCS signals used in this MCU.
0 Negate the PCS[.] signal.
1 Assert the PCS[.] signal.

So probably by changing this, plus some other setup stuff, I can manually toggle CS,DC and still use the more efficient SPI register operations. Maybe. In any case, another milestone marker passed, :-).

EDIT:
In any case, I'm following what you guys are doing with the LCD libraries, as I may be able to take advantage for my Teensy project. Thanks.

Victor and Ray

Ok. Sounds like everyone is pretty much in agreement ? about adding SPI.DMATransfer() to the existing library

Albeit we'll need to work out the details of how CS is handled.

I guess we have 2 options

a) Pass in the pin number so that DMATransfer can assert and de-assert as part of the transfer
b) The calling function needs to assert CS before calling DMATransfer, in which case we'd need a callback function pointer to be passed to DMATransfer, so that the calling code can be notified when the transfer is complete (and also that the SPI bus is no longer busy). The callback function, can then de-assert the CS line

I'm not that keen on the DMATransfer code asserting / de-asserting CS, as normally this is done by the code that calls SPI.Transfer()

I just had the thought that the new Transactional SPI stuff may be supposed to handle the CS line, but the only reference I can find is on the Teensy site SPI Arduino Library, connecting SPI devices to Teensy

SPI.beginTransaction(SPISettings(clockspeed, MSBFIRST, SPI_MODE0))

Begin using the SPI bus. Normally this is called before asserting the chip select signal. The SPI is configured to use the clock, data order (MSBFIRST or LSBFIRST) and data mode (SPI_MODE0, SPI_MODE1, SPI_MODE2, or SPI_MODE3). The clock speed should be the maximum speed the SPI slave device can accept.

digitalWrite(SSpin, level)

Most SPI devices define a transfer of multiple bytes. You need to write the SS pin before the transfer begins (most chips use LOW during the transfer) and write it again after the last byte, to end the transfer. See below for more SS pin details.

SPI.endTransaction()

Stop using the SPI bus. Normally this is called after de-asserting the chip select, to allow other libraries to use the SPI bus.

Which seems to suggest that the Transactional stuff is only used to set the spi clock speed etc, and doesnt handle the CS line

So basically, as far as I can see, its not the SPI libs responsibility to assert or de-asset CS, hence the function that calls DMATransfer, needs to be told when the transfer is complete, hence I think we need a callback for this.

i.e option (b) above

I'm not sure if its just the terminology, but the DMA code is not a class, its just a series of functions.

Well, crap. I should probably not write in the forum after dinner and 3 beers.

What I was thinking when I posted my flawed logic was along the way that Limor handles her GPS code by capturing SoftwareSerial. In the case of the Maple-centric SoftwareSerial, it looks like:

SoftwareSerial::SoftwareSerial(uint8_t receivePin, uint8_t transmitPin, bool inverse_logic /* = false */)
{
 if (receivePin == 0 && transmitPin == 1) {
 port = &Serial3;
 } else if (receivePin == 8 && transmitPin == 9) {
 port = &Serial2;
 } else if (receivePin == 25 && transmitPin == 26) {
 port = &Serial1;
 } else {
 port = NULL;
 }
}

SoftwareSerial::~SoftwareSerial()
{
 end();
}

Then in my main sketch, I pass the GPS object the address:

// create mySerial object for exclusive use by Adafruit_GPS
SoftwareSerial mySerial(0, 1);          // Rx Tx : Connect the GPS TX (transmit) pin 0 (NC on pin1)

Adafruit_GPS GPS(&mySerial);                                      // create GPS object

The user code can detect when the 1st buffer has filled from serial interrupts and move on while the 2nd buffer is being loaded...

char c = GPS.read();                                            // read data from the GPS and check for full sentence
  if (GPS.newNMEAreceived()) {
    if (!GPS.parse(GPS.lastNMEA()));                              // sets the newNMEAreceived() flag: return; no longer used
  }
...

But, honestly, sticking in more functionality as functions and implementing a callback is Ok by me. It needs to work with old Maple examples and it needs to cover the new uses.

Ray

Ray, I agree it should be compatible with old code, I think that should be the 1st concern.
If we add a new DMA transfer function, with a new name such as SPI.DMATransfer (), it should not interfere at all with previous code that doesn't use it.

About the callback, I believe it should be easy to implement with the ISR.

I propose something like this:
1 TX SPI.DMATXTransfer (*char src, uint16_t n bytes, *callback pointer OR optional CS to toggle before return); any returned byte is dropped.

1 RX SPI.DMARXTransfer (*char dst, *char src OR byte (where byte is to be sent over and over for n times), uint16_t n bytes, *callback pointer OR optional CS to toggle before return);

Internally, it if the user pass a callback pointer, it sets the ISR to call that callback on interrupt, fires the transfer, returns right away and will notify with the callback. If the user instead pass a CS to toggle, it sets the ISR to call a callback defined within the library to toggle the pin for the user. If the CS is passed as a parameter, it does not return until transfer is over.

My logic on that is, if the user does not need to do other stuff while the DMA is going on, it simplifies the use of the library, specially for new users. We can even remove the CS toggling from here altogether, and have the callback pointer as optional. If not passed as parameter, it will use it's own and block until complete transfer.
If the user wants to use the callback, then I think CS is better managed outside the DMATransfer function.

Just for reference, this is how it is done in the SdFat and the ILI_due libraries right now. The structure is copied from how they had it set up in the due, it could be simplified more:
https://github.com/greiman/SdFat/blob/master/SdFat/SdSpiSTM32F1.cpp

One more note, why I want to pass 2 pointers to the RX function with a buffer to send?
Imagine you need to send 4 bytes with a command, and receive 512.
Instead of setting a 4 bytes DMATX, and then a 512 DMARX sending blanks, you could set up a 516 bytes transfer. In the TX buffer write your 4 commands at the start of the buffer and fill blank the rest. The receive buffer 516 bytes long too. Then you fire a RX that will transmit 4 bytes with your command, and receive 4 empty responses to those 4, and the 512 bytes that you were expecting. With a single DMA setup you sent the command and received the data.
Given that I think buffers should be setup once with their maximum size and just used over and over, I don't see a problem wasting a bit of memory. You can even setup multiple command, blanks n bytes, command, black n bytes if you know you will need to do those 2 transmissions in sequence in advance. If you don't want to use the feature, just send the commands by yourself, and set the RX to just send 00 or FF over and over, doesn't need a buffer to do that.

I just had the thought that the new Transactional SPI stuff may be supposed to handle the CS line, but the only reference I can find is on the Teensy site SPI Arduino Library, connecting SPI devices to Teensy

Roger, I looked at that stuff on Monday when I was having my Teensy SPI RAM vs ST7735 buss contention problems. Unfortunately, it didn't do much for me. Here's the problem, you can look at the source on this page - note that SPI.h has about 4X as much "source code" in it as does SPI.cpp, ummm. Also, note the different sections for AVR, Teensy, etc.

He wrote some code here, for SPI setup and transfers, but then he overwrote it in the ST7735 library, so this stuff no longer seems effective - or work. I'm not quite sure.

	// Before using SPI.transfer() or asserting chip select pins,
	// this function is used to gain exclusive access to the SPI bus
	// and configure the correct settings.
	inline static void beginTransaction(SPISettings settings) {
		if (interruptMasksUsed) {
			__disable_irq();
			if (interruptMasksUsed & 0x01) {
				interruptSave[0] = NVIC_ICER0 & interruptMask[0];
				NVIC_ICER0 = interruptSave[0];
			}
			#if NVIC_NUM_INTERRUPTS > 32
			if (interruptMasksUsed & 0x02) {
				interruptSave[1] = NVIC_ICER1 & interruptMask[1];
				NVIC_ICER1 = interruptSave[1];
			}
			#endif
			#if NVIC_NUM_INTERRUPTS > 64 && defined(NVIC_ISER2)
			if (interruptMasksUsed & 0x04) {
				interruptSave[2] = NVIC_ICER2 & interruptMask[2];
				NVIC_ICER2 = interruptSave[2];
			}
			#endif
			#if NVIC_NUM_INTERRUPTS > 96 && defined(NVIC_ISER3)
			if (interruptMasksUsed & 0x08) {
				interruptSave[3] = NVIC_ICER3 & interruptMask[3];
				NVIC_ICER3 = interruptSave[3];
			}
			#endif
			__enable_irq();
		}
		#ifdef SPI_TRANSACTION_MISMATCH_LED
		if (inTransactionFlag) {
			pinMode(SPI_TRANSACTION_MISMATCH_LED, OUTPUT);
			digitalWrite(SPI_TRANSACTION_MISMATCH_LED, HIGH);
		}
		inTransactionFlag = 1;
		#endif
		if (SPI0_CTAR0 != settings.ctar) {
			SPI0_MCR = SPI_MCR_MDIS | SPI_MCR_HALT | SPI_MCR_PCSIS(0x1F);
			SPI0_CTAR0 = settings.ctar;
			SPI0_CTAR1 = settings.ctar| SPI_CTAR_FMSZ(8);
			SPI0_MCR = SPI_MCR_MSTR | SPI_MCR_PCSIS(0x1F);
		}
	}

	// Write to the SPI bus (MOSI pin) and also receive (MISO pin)
	inline static uint8_t transfer(uint8_t data) {
		SPI0_SR = SPI_SR_TCF;
		SPI0_PUSHR = data;
		while (!(SPI0_SR & SPI_SR_TCF)) ; // wait
		return SPI0_POPR;
	}
	inline static uint8_t transfer16(uint16_t data) {
		SPI0_SR = SPI_SR_TCF;
		SPI0_PUSHR = data | SPI_PUSHR_CTAS(1);
		while (!(SPI0_SR & SPI_SR_TCF)) ; // wait
		return SPI0_POPR;
	}
	inline static void transfer(void *buf, size_t count) {
		if (count == 0) return;
		uint8_t *p = (uint8_t *)buf;
		SPDR = *p;
		while (--count > 0) {
			uint8_t out = *(p + 1);
			while (!(SPSR & _BV(SPIF))) ;
			uint8_t in = SPDR;
			SPDR = out;
			*p++ = in;
		}
		while (!(SPSR & _BV(SPIF))) ;
		*p = SPDR;
	}

	// After performing a group of transfers and releasing the chip select
	// signal, this function allows others to access the SPI bus
	inline static void endTransaction(void) {
		#ifdef SPI_TRANSACTION_MISMATCH_LED
		if (!inTransactionFlag) {
			pinMode(SPI_TRANSACTION_MISMATCH_LED, OUTPUT);
			digitalWrite(SPI_TRANSACTION_MISMATCH_LED, HIGH);
		}
		inTransactionFlag = 0;
		#endif
		if (interruptMasksUsed) {
			if (interruptMasksUsed & 0x01) {
				NVIC_ISER0 = interruptSave[0];
			}
			#if NVIC_NUM_INTERRUPTS > 32
			if (interruptMasksUsed & 0x02) {
				NVIC_ISER1 = interruptSave[1];
			}
			#endif
			#if NVIC_NUM_INTERRUPTS > 64 && defined(NVIC_ISER2)
			if (interruptMasksUsed & 0x04) {
				NVIC_ISER2 = interruptSave[2];
			}
			#endif
			#if NVIC_NUM_INTERRUPTS > 96 && defined(NVIC_ISER3)
			if (interruptMasksUsed & 0x08) {
				NVIC_ISER3 = interruptSave[3];
			}
			#endif
		}
	}

You'll notice that in beginTransaction(SPISettings settings), settings only deals with basic SPI aspects like bitrate, mode, data order. Then, you'll notice that endTransaction(void) only deals with possible interrupts having been used, and nothing about SPI setups. There is nothing in here to deal with the ST7735 library having overwritten the setups to use automatic CS activations, etc. So, he has

SPI0_PUSHR = data; here, but he has

SPI0.PUSHR = c | (pcs_data << 16) | SPI_PUSHR_CTAS(0); in the ST7735 library, as mentioned yesterday.

I'm not certain whether the effects of using this last statement actually "release" the SPI buss properly, but it doesn't seem to in my program, as mentioned yesterday.

On and on - however, you can probably use the basic transaction idea, but just straighten things out better, and don't have your "optimized" SPI LCD libraries screwing everything up.

Adafruit_SSD1306_STM32 library
Hello,
today my 128x64 I2c Oled's arrived (haitec.cn).
I've done successfully a port of the adafruit_SSD1306 library and called it Adafruit_SSD1306_STM32 (it's not compatible with avr/sam anymore, I have not the time for such gadgets)
Some things to know:
Only I2c is tested! I've done the typdef conversation for SPI, compiles ok, but I cannot test it!
This adaption uses hardware I2C (hardwire.h), instead of "wire.h" (I hate the software bitbang digitalWrite mess up thing)
Port: I2c2. SDA=0, SCL=1 on maple mini
To change it to Port I2C1: (*.cpp file on the top)
//HardWire HWIRE(1,I2C_FAST_MODE); // I2c1
HardWire HWIRE(2,I2C_FAST_MODE); // I2c2

Don't forget to setup the correct I2c address in your code! With my display:
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);

Adafruit_SSD1306_STM32.zip (25.1 KB)

All I can say is ... YES! The darn thing is finally working end-to-end on the Teensy 3.1 board.

I put the OV7670 system all back together, and used the new ST7735 library that I patched yesterday, and am finally getting good image captures to SPI RAM.

OV7670 image -> SPI-RAM -> ST7735 LCD display

Getting rid of the LCD SPI optimizations fixed it, so the 23LC1024 RAM can now get onto the SPI buss properly.

Roger, here are a couple of points you might take note of.

  1. using the regular SPI.transfer function to capture OV7670 data is too "slow" for 24 and 48-MHz
    T3.1 clock speeds, but it works fine at 72 and 96-MHz.

I was getting images displayed as 4/ea 80x60 blocks on the LCD for the slower T3.1 clock speeds, which indicates each run though the capture loop was missing 1/2 the data. The higher clocking fixed this.

  1. besides adding an hsync before each capture, as I mentioned previously, I also played with
    having the PCLK sync both ways shown below, as having it the wrong way produces hash;
    this is obviously tied up with how fast the code is going.
      wait_pclk_high();   // get hi-byte;
      SPI.transfer( (uint8_t)(GPIOD_PDIR & 0xFF) );
      wait_pclk_low();

-VERSUS-
      wait_pclk_low();   // get hi-byte;
      SPI.transfer( (uint8_t)(GPIOD_PDIR & 0xFF) );
      wait_pclk_high();

Amazingly, right now the captures with 96-MHz T3.1 are no faster than with the mega1284 board, so next to try some speedup measures, and also move over to the ILI9341 320x240 LCD. Whew!

Ray and Victor

I think we are all in agreement.

Adding 2 new functions to the SPI class will not have any issues for old code

Normally the compiler doesn't link in functions that are not used but with libmaple it may be linking all functions because of the whold_archive flag. I will check if adding a new function to SPI makes it bigger

@victor, I see what you mean about one function that doesn't return until the transfer is complete, which saves needing to write a callback function, and can be used if you only have one think you want to transfer quickly and don't need it to run Asynchronously.

And another function that returns straight away and then calls back on completion.
Both functions internally to the SPI lib need to use the ISR callback, its just that on the Asynchronous call, that the ISR calls the callback when its finished.

@ray

I don't think I explained things very well about my thoughts on begintransfer()

I totally agree it just changes the settings.

I'm not sure why the transaction system was added really, when the same effect could be achieved by calling set divider and set bit order.

Dan

Ok. So you are transferring to SPI RAM straight away. As Pclock is only around 1 MHz , it should be possible to transfer to SPI at that rate, ie you'd need SPI speed set as fast as possible, as its going to take at least 16 cycles per byte using DIV2

I will try to get back to my ov7670 test rig and read the low res image straight into internal ram, and then I will need to write code to rotate and then write to the LCD, as the ILI9341 display I have is portrait but the camera is landscape

the ILI9341 display I have is portrait but the camera is landscape

Roger, both LCD libraries have a set-rotation function.

The Teensy sets the SPI clock rate in both the SPI and ST7735 libraries, but the commenting is so skimpy, I'm not sure what the values even are. Will have to play with this now that it's all working. I should also be able to step up the PCLK rate by 2X or 4X.

I initially had the image captures going into the internal RAM of the T3.1 chip, and that worked straightaway with no hitches. But you can only store a 160x120 image in there [with 2 bytes/pixel it takes 38KB], so I needed the external SPI RAM to handle 320x200 images for the ILI9341 LCD. The system is now capturing from camera straight to SPI RAM, and outputting from SPI RAM straight to LCD, with no buffering needed inside the T3.1 chip.

BTW, I am still using the mega1284 to configure the OV7670 at startup, and am using the straight unmodified Rduino IDE Wire library, as I mentioned a couple of weeks ago. Wire works fine with the Rduino. Now will play with doing the camera setup in T3.1 code.

Hi Dan

OK re: RAM. I'm using a F103RCT based board, which has 64k ram !!
( http://www.st.com/web/catalog/mmc/FM141/SC1169/SS1031/LN1565/PF164486 ) so there should be enough ram for both the image and the variables in the code. i.e there should be 26k free for vars which should be enough

I'm setting the camera up using the Wire lib on the STM32, which also works OK, but I did have to slow the data rate down to 100kpbs, but I think this is mainly due to my pullup resistor values. If I used lower values I may be able to use the default rate for the library which is 250kbps
(but it could just be that the bus timing for SCCB is not the same as for I2C and its will only every work using the Wire lib when its run slowly)

I was hoping to get some time today to look at this, but I have some bugs to fix for my day job, so I doubt I will be able to look again until the weekend

Yeah, T3.1 also has 64KB internal RAM, so both chips have enough for 160x120x2bytes.

I've been looking at this board. $24 inc LCD, jeez, would be great for directly hooking the OV7670 or other camera.

They mention using the following dev tools, which I think are all expensive. Any chance your guys' disto will work with this board?
http://www.st.com/st-web-ui/static/active/en/resource/technical/document/user_manual/DM00097320.pdf
– IAR Embedded Workbench® for ARM (EWARM) by IAR Systems
– Microcontroller Development Kit for ARM (MDK-ARM) by Keil™
– TrueSTUDIO® by Atollic

@Roger, if you start writing the functions let me know. Otherwise I may have time this weekend to start writing them. About the F103RCT, doesn't that have 48KB?

@Oric, it seems like the STM32F4xx are very different devices than the F1xx. Registers, peripherals, even the core is different as one is Cortex M4 with FPU and the other Cortex M3. There is one other repository for STM/arduino that is adding support for F4xx parts, but not sure if the F427 is supported.
You may want to look at coocox for a free IDE. I have read good things about it, although I have not used it.
Roger found an F103VEZ board, that device has 1MB of flash, and the board even has an eeprom and a spi flash on board for around $15, a display this days is just $4 or 5, so for the same price of the F427 discovery, and an F103VEZ is more likely to use most of the code in this repo with little change, as the cpu core and most peripherals are similar.

There is a link posted in this thread a couple of pages back, have a look at that.

Personally, I got a Nucleo F411 board, I wanted something compatible with mbed to try it out, and that seemed like a good option. I haven't used it yet. In fact I think I haven't compiled anything that needed more than 40kB, so I am still far from filling the maple mini.
I remember the days I programmed pic12 in assembler, with 512 bytes of flash and 20 or so of ram... That was the last thing I programmed until this days with the Arduinos.

Dan Victor

About the F103RCT, doesn't that have 48KB?

Not sure. The spec says, up to 64K but then doesnt seem to mention any other ram sizes, normally ram in a series e.g. the R series is the same, its just the Flash size is bigger in the RE than the RC version

C = 256 Kbytes of Flash memory
D = 384 Kbytes of Flash memory
E = 512 Kbytes of Flash memory

Re: Other board

I have a F103ZET board know, which does have external FLASH ram connected to SPI, but I've not had time to investigate how to use it, and I'd need to disconnect all the wires from the RC board, which I ended up having to solder to the back of the RC board as I didnt have enough push on connector wires for the large number of wires needed to connect the camera (I have since ordered some more wires, so will probably unsolder the camera when those wires arrive and move it to the ZET board)

The VET and ZET boards are a good match for the camera s they are still not hugely expensive i.e less then $20 US and have Flash ram and also an SD card socket (actually it depends which board you get but these things are available)

Re:F11 nucleo

I have an F4 discovery, but have only managed to get the Blink stuff to work with the code thats in the repo. The F4 stuff is an old derivaite of libmaple from well before Bob and I started to bring it up to date with IDE 1.6+

You could try giving it a try with your Nucleo board, but don't expect serial to work, just try blinking, that may work !

Edit.

Victor, I'm hoping to get some free time later today so I will investigate writing those functions and let your know (PS. I'm on UTC +11 currently, so its just after lunch here)

@dan

Use CooCox or Em:Blocks if you want to use STM's own libs

You can get a free copy of Keil, but it has a limit of the max program file size

Also I got bogged down with keil as its modular and I couldnt figure out what modules I needed to install to get it to work with the F103

If you do decide to use Keil, you can use the GCC compilor with it, by changing a a load of settings (there are web pages about how to do this, which I'm sure you can find)

CooCox worked quite nicely for me, as long as you tick the correct boxes to load the correct libs and templates

I think I also had a go at Em:Blocks and it seemed to work, but all I was going was flashing a LED

However the Arduino IDE hides all the messy stuff about setting GPIO, e.g. just pinMode() takes about 20 lines of code to configure a single GPIO pin

and there is a lot of other stuff as well like the RCC and AFRemap stuff that you need to put in, if you are coding from scratch ;-(

@Dan: Also worth a look into: (Didn't here about it till I got a advertisment from ST last week)

should be available for linux and OSX Q2/15

Thanks for the info, guys. I'm pretty much buried with the Teensy, but liked the F4 board due to it's having the LCD built in. Would be easy to hook to the camera directly. Better than having 35 dangling wires.

@victor_pv

I hope you don't mind, but I'd like to re-instate the old - non-dma version of the ILI9341 lib that you zipped up, as it can co-exist with the other DMA versions, and It will be helpful for me to have a version if the lib that I can test with a DMA version of the SPI class

Also, looking at the file name Adafruit_ILI9341_STM versus the class name for Adafruit_ILI9341 , by convention the class name is the same as the file name, so I'm going to change it to match the file name, I'll also change the examples, so that they reference the correct class name.

Note the Due file / class is OK because it uses the class name ILI9341_due and the file name is ILI9341_due.cpp

Thanks

Roger

Edit

I've now made the change and pushed it to the repo.

I've updated all of the examples, and have tested most of them. Actually one or two of the examples don't currently work, because they seem to call functions not in the library, but I'm pretty sure that the problem has not been caused by this change and was probably there before the change.
(though I could be wrong ;0) )

Roger I don't mind at all.
I kept the files zipped for that purpose, in case the non-DMA version was needed again.
About the file name change, I think it should be fine, as that should affect only at the point of instantiating the class, correct? so that would involve just changing 2 lines in the sketches, not a big deal.

About the examples, the ones I tested would have my DC, RST and CS pin definitiong, that were 8 9 and 10, so any example that has those, was one I tested and worked. If it doesn't have those pins, then I did not test it.
I can have a look at the ones not working. Do they work with the non-DMA version of the library?

I think we should freeze further changes to libraries using DMA until we have the new functions in the SPI library anyway, then we can optimize using them.

Just a note, on the due one, I still don't quite understand why the original author included his own copy of some of the sdfat files, with changes in the class names and little more than that. It would make more sense to just require the sdfat libraries to be available and use them.

madias:
Adafruit_SSD1306_STM32 library

Thanks!

I have a different OLED with same resolution: 2-color mono display

I got my OLED working this morning using Software SPI. It's refusing to work using Hardware SPI, but I have no time today to dig into this issue... No issue with Hardware SPI and ILI9341 previously.

I also tried it on Nano328 and it worked using same pin numbers (unmod libs!):

 // software SPI works on Maple Mini ARM 32-bit
  // use these settings for the OLED_Pro smart display...
  // These pin #'s are for Maple Mini/UNO/Nano/Mini328
  #define OLED_DC    6  // D/C
  #define OLED_RESET 5  // RST
  #define OLED_MOSI  4  // SDA
  #define OLED_CLK   3  // SCL
  #define OLED_CS    7  // Not Connected to OLED board
  Adafruit_SSD1306 OLED(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);

Ray
OLED on the cheap...

IMG810_web.jpg