"Improving" the AXE133 (OLED) Firmware ?

AllyCat

Senior Member
Hi,

Well, I finally assembled the AXE133 OLED board that I couldn't resist in the Black Friday sale :) . But now there are several hardware enhancements available, such as the "backlight" dimming from nick12ab, and adding a "DS3231 for PI" Clock and Temperature module by marks (post #7). So I want to add a command (control code) to adjust the brightness, and in due course probably other features such as selectable baud rate/pin/polarity and directly updating the message text, etc..

However, there are many threads on the forum which indicate that the timing of the code is critical, to avoid characters being lost or corrupted. I don't want to write lots of new program code and then discover that it doesn't work reliably, so I analysed the timings of all the individual instructions in the critical part of the main loop in the AXE133 program. The original code is quite "fast", but I think it can be done faster. ;)

My preference is to do all PICaxe timing estimations at the default 4 MHz clock frequency (of M2s), because then each PIC instruction cycle (and the period of "Timer 1") is exactly one microsecond. However, the standard AXE133 code runs at 16 MHz (to receive data at 2400 baud), but I will consider the equivalent baud rate at 4 MHz (600 baud) and convert up to 8 MHz/1200 baud and 32 MHz/4800 baud, etc. when required. 600 baud has a bit period of ~ 1600 us.

Although PICaxe Basic has several "high level" coding structures (IF..THEN..ELSE , DO..WHILE/UNTIL , CASE..SELECT, etc.) the base PIC (and I suspect the PICaxe interpreter) has only an elementary "Jump" (GOTO) instruction, with the other structures being converted by the Program Editor / Compiler. Also, the two paths from a "branch" instruction have different execution delays; the "fall through" is faster than the "jump" (to another part of the program), principally because the Program Counter needs to be reloaded. So my first task was to identify how the IF..THEN..ELSEIF.. commands in the basic program are converted to GOTOs (tokens).

This is not trivial because the different IF... structures behave differently! IF <true condition> THEN {GOTO} obviously invokes a jump and the <false condition> is a (faster) fall-through into the next line of the program. However, the IF <true condition> THEN <newline> structure falls through to the next line, whilst the <false condition> (to ELSE / ENDIF) uses a (slower) jump to elsewhere in the program. Of course the true/false conditions are complementary, so either path structure is possible, but it appears that (at least in the AXE133 code) the PE inverts the true/false test so that the false result causes a jump and true falls through.

So now, here is the critical part of the code in its original form and then converted to use only GOTOs, complete with some approximate execution times at 4 MHz :

Code:
main:
	serin RX,baud,b1			; wait for the next byte
	; NB keep character mode test as first item in this list to optimise speed
	if b1 < 253 then
		let pinsB = b1 			; output the data
		pulsout enable , 1  		; pulse the enable pin to send data.
		goto main			; quickly loop back to top
	else   .......
	else   .......

; IS (probably) EQUIVALENT TO :

main:
	serin RX,baud,b1			; Wait for the next byte   
	if b1 => 253 then goto notchar		; Fall through = ~ 850 us (= PIC cycles)
	let pinsB = b1 				; Output the data  = ~ 500 us
	pulsout enable , 1			; Pulse the enable pin to send data  = ~ 500 us
	goto main				; Quickly loop back to top  = ~ 850 us  = Total = ~ 2700 us 
notchar:					;  Jump to here   = ~ 1250us
;        Continue decoding
;
The goto main represents a significant delay (before the next character can be received) but this can be reduced by rearranging the program loop :

Code:
character:
	let pinsB = b1 				; Output the data  = ~ 500 us
	pulsout enable , 1			; Pulse the enable pin to send data  = ~ 500 us   
main:
	serin RX,baud,b1			; Wait for the next byte   
	if b1 < 253 then goto character		; Jump back = ~ 1250 us  , Total = ~ 2250 us
notchar:					; Fall through  = ~ 850 us
This is a "win-win" situation because both the main loop and the notchar path are reduced by around 400 us each. Of course at the beginning of the program we need to jump into the loop at main: (or initialise b1 as a non-printing character) but this seems a small price to pay.

Note that the second (and each subsequent) ELSE in the original program adds another delay of ~ 1250 us, which pushes the path delays for codes 253 and 255 well past 3000 us. Generally it would be better for a "true" to jump out of the list, so that each test adds a rather smaller ~ 850 us to the longest path. These particular paths are not quite so time-critical as the "character" loop because the (present) commands all receive an additional parameter, so there is no need to jump back into the main loop immediately. Actually, that might be a useful strategy when adding any additional commands, even if the reception of an additional byte is not strictly needed.

A structure which is considerably faster than a series of IF...ELSEs is the ON var GOTO label0 , etc.... . The first jump (to label0 for var = 0) takes a time similar to a normal GOTO, but then each subsequent label adds only around 250 us (i.e. about 5 times faster than the original ELSEs). Furthermore, the last label can be omitted from the list and instead executed as a (faster) fall-through. But a problem is that the var list must start from zero, which is where the User Definable Characters are located. Calculating an "offset" adds a significant delay: (b1 = b1 - offset is ~ 650 us), particularly if we need to retain the original value (i.e. b2 = b1 - offset takes ~ 1000 us).


But now to the main point of this thread: What additional commands do others think might be useful in the AXE133 controller and how (or if) the command set should be restructured ? The present commands (253, 254, 255) overlay existing characters in the ROM, which thus cannot be used. They're not "essential" characters, but 255 is a solid block which at least might be useful for testing. AFAIK the character codes between 16 and 31 are not used at all, so are an ideal place to locate the command codes. But that requires a (slower) double-test (greater than and less than conditions) before a value can be definitely identified as a character (if the User-Definable Characters are included).

However, the AXE133 character map has the 8 User-Definable Characters (0 - 7) duplicated between 8 and 15, so why not locate all the command codes between 0 and 7 and use the higher group of UDCs ? Does anybody know of any character sets that (e.g.) have 16 UDCs, or located only from zero upwards? Alternatively, would it be useful to decode more character codes "on the fly" (e.g. to allow codes such as 13 <Carriage Return> and 10 <Line Feed>) to add functions such as "Newline" and "Scroll")? But that may require much more effort in checking all the worst-case timing delays. :(

Cheers, Alan.
 
Last edited:

techElder

Well-known member
Just wish I had time to help with this, but I don't even have an AXE133. I've used other displays, but have always addressed them directly.

Perhaps if you can present options for possible command additions that make sense for a larger audience to comment on?
 

stan74

Senior Member
I just looked at axe133
; Supported Commands
; 0-7, 8-15 CGRAM characters
; 16-252 normal ASCII characters, according to selected character map table
; 253, X display 16 character pre-saved message from EEPROM memory, X can be 0-15
; 254, X LCD command, X can be 0 to 255
; 255, X control outputs C.2, C.1, C.0 (via lower 3 bits of X)
; So, if using a backlit LCD with the active low transistor driver
; on output C.2, then 255,%000 switches backlight on and 255,%100 switches off
Aren't the codes fixed by the lcd,not the picaxe controlling it? Different lcds different codes.
You could pwm the back light but c.2 shares the servo.
udgs from 0..add 15? any character can be a black square. Not sure what you mean.
Can't marks program be altered to serial? lcds are slow anyway.
Must be plenty of character sets around. Here's what I found for my oled. Glad I found it. Look at Display_Char sub.
http://colemanair.us/vp_asp/scripts/articles/OLEDandLCD.htm
 

hippy

Senior Member
The original code is quite "fast", but I think it can be done faster. ;)
You are quite right; as you have demonstrated, and I your analysis looks to be correct.

I think it was a case for us that making the code faster did not seem to make it any better or more useful in general which led us to keep what we had rather than spend time optimising it further. The goal was being able to take sequential characters and 254,x dual command codes at 2400 baud with everything else secondary to that.

It is converting the initial "IF b1 >= 253 THEN" to "IF b1 < 16 OR b1 >= 253 THEN" to allow handling any characters $00 to $0F while still being able to handle the printable characters and be back ready for the next which I think had us ignoring those. We did not need those so never pursued it further.

Refactoring the code as you have done might allow additional command codes to be added as it reduces the time from the getting the first byte to being ready for the second. I don't think we worried about that because we did not have or need any other command codes to support. It may be possible to add additional decoding for existing 253,x / 254,x / 255,x commands to add more command options.

One useful option to add may be a means to read bytes and buffer those up to a terminator and then churn those out at high speed. Optimising that read loop may allow higher baud rates to be used - as well as more instant whole display updates - but comes at the expense of not knowing exactly when you can send the next block of data. For code which only outputs every 10 or 20ms that should likely not be such a problem. Something like ...

Code:
BufferedInput:
  SetFreq M32
  bPtr = 2
  Do
    SerIn RX, FASTBAUD_32, @bPtr
  Loop Until @bPtrInc = $00
  bPtr = 2
  Do
    b1 = @bPtrInc
    Select Case b1
      Case 0
        Goto BufferedInput
      Case < 253
        :
    End Select   
  Loop
While outputting the buffer can be optimised, it is not so essential that it is.

I would suggest adding the option to enter the buffered mode under 255,x as that only uses three bits of parameter 255,0 to 255,7, change ...

Code:
	else ; must be 255
		serin RX,baud,b1		; wait for the next byte
		let pinsC = b1 & %00000111 | %10000000
		goto main
	end if
to

Code:
	else ; must be 255
		serin RX,baud,b1		; wait for the next byte
		if b1 = 255 then BufferedInput
It would be interesting to see how fast you could get buffered input running.
 

Flenser

Senior Member
Does anybody know of any character sets that (e.g.) have 16 UDCs, or located only from zero upwards?
This table comes from the Hitachi HD44780U (LCD-II) Manual ADE-207-272(Z) '99.9 Rev. 0.0. It appears that there were only 2 character sets provided by Hitachi, one Japanese and one European.
Ordering Information.jpg

However, the AXE133 character map has the 8 User-Definable Characters (0 - 7) duplicated between 8 and 15, so why not locate all the command codes between 0 and 7 and use the higher group of UDCs ?
The charaters are not duplicated. The manual states that "character code bit 3 has no effect" so if you treat bit 3 as always being value "0" then character codes Hex 08 to 0F are effectively translated to Hex 00 to 07. So you could choose to use either codes Hex 00 to 07 or codes Hex 08 to 0F for your own purposes. It might be least confusing if you leave codes Hex 00 to 07 for the CGRAM and overloaded codes hex 08 to 0F.

In the European standard font, ROM code A02, the character codes Hex 10 to 20, 80 to A0 and FE are all empty so if you intended your modified code to only be used with the European standard font, and not the Japanese standard font, then you could choose to use one or more of these codes for your own purposes .
Table4 80%.jpg
 
Last edited:

marks

Senior Member
Hi AllyCat,
I only read this thread quickly but I also did some code for the axe133.
http://www.picaxeforum.co.uk/showthread.php?19474-Learning-to-Drive-an-LCD-DISPLAY/page3
when i received an oled I added the post at #21 which you can try.

before that post #18 and #19 lcd examples,its probaly not so clear but 8bit throughout the thread generaly refers to the axe133.
at the time I was trying to write generic code that would also work with 20x2.
and in the future intented to go back and rewrite specifically for the 18m2 as i know i can make this quicker.
I think a poll would be interesting to see different ideas

clock alarm
temperature monitor /control
message scrolling line2 ?
mimic the terminal program
I guess the list could be endless and unfortunately everyone likes to do these things there own way,
and some others stick rigidly to rev ed programs.for me its small steps in the areas of interest as time permits.
 

hippy

Senior Member
I guess the list could be endless and unfortunately everyone likes to do these things there own way, and some others stick rigidly to rev ed programs.
That's the reality of it. The best one can do is modify things to be how you want them to be and invite others to use those solutions. But everyone will have their own ideas of how things should be.
 

AllyCat

Senior Member
Hi,

Thanks for all the replies; just a few comments for now, to show that they are being inwardly digested.

The original AXE133 program overlays the top 3 characters with command codes so that it can access the User Definable characters (0 - 15) and the ROM characters with a single test (i.e. < 253). Also, at least some of the Winstar displays have character sets (Japanese/Russian) that fill the entire region from 16 ($10) up to 255 ($FF), so the only area to put control codes, without sacrificing ROM characters, is below 16. But it does seem that each of the User-Definable Characters is (always?) accessible at two addresses, so there are potentially 8 "spare" locations.

0-7 would be the more efficient location for control codes (because only one test to separate them from Characters is required) but many users/programmers may not appreciate that. I don't normally like "compound" logical operations but it happens that the additional execution time required for IF b1 < n1 OR b1 > n2 THEN.... is very similar to what was saved by re-ordering the original AXE133 program. So my inclination is to move the control codes to the range 8 - 15, which is easy to apply in both decimal and Hex, e.g. 255 --> 15 (or $FF --> $0F), etc.. But with the two tests available, any (single) region could be used.

Like hippy, I considered extending the use of code 255, or now 15, (in my case for the DAC/PWM brightness control) but the additional logic introduces a significant execution delay. Of course some commands (such as the pre-defined messages) take a considerable time to execute anyway, so my current plan is to read the additional "parameter" into a different variable (register). Then use an ON..GOTO to process any additional commands, perhaps even the full range from 8 to 13. The more time-critcal can be given a preferential (fastest) location in the list of labels.

My original post was already (too) long, so I omitted that I also have a secondary target, to port the code onto a different PICaxe. Like iwp, using the 4-bit mode, interrupt driven, and a buffer as suggested by hippy. But in my case, using an 08M2 with an I2C expander as already fitted to many similar LCDs. Much of that work has already been done some time ago and achieved at least 4800 baud at m16, but was put on the "back burner" until I could decide on an extended command protocol and best hardware configuration.

Cheers, Alan.
 

Goeytex

Senior Member
Any improvement from the annoyingly slow 2400 baud rate and subsequently slow character rate is certainly good, but it seems like an awful lot of effort just to increase the character rate by such a small amount.

While the optics of the slow character rates related to 2400/4800 baud may be somewhat annoying, in many cases it can be lived with since the application does not require that the program move along quickly to do other stuff. However, in other applications waiting 200 ms for the display to refresh can be a deal breaker.

I had such an application quite a while back. So I replaced the 18M2 on the AXE132 board with a PIC 16F1847 and ported the 18M2 firmware to ASM. Similar to what Rev-Ed did with the old FRM010 Firmware Chip (except that the baud was selectable at either 9600 or 38400 baud. 38400 gave a character rate of about 3,300 CPS which was acceptable. Consider that the display is capable of > 20,000 CPS.

Seems to me like Rev-ed might want to do something similar and offer its customers a firmware written in ASM or C that can speed up these very nice OLED displays.
 

AllyCat

Senior Member
Hi,

Yes, doing anything (even slightly) more quickly with a PICaxe often takes more effort than writing directly in assembler. So I hope that this promised feature does eventually appear, but I have a horrible feeling that it will go the same way as brackets in maths expressions. :(

Tha PICaxe Basic documenattion is quite reasonable, but the "deeper" stuff needs a lot of detective work. For example, does SERIN start only with the rising edge of the start pulse, or on any positive level. Normally that would be a daft question, but the critical timing betweeen characters means that it may be more sensible to start on a positive level than wait for the next rising edge (which might well be the wrong one). Similarly, does it check for the Stop Bit? There's not much point because PICaxe Basic doesn't really have any error-handling strategy. So we might be able to set up a (non-PICaxe) serial transmitter with a parity bit (ignored) and two stop bits, to give more than double the normal inter-character time. Who knows? :)

One of the purposes of this thread was to see what else the AXE133 might be able to do, since it has a more "powerful" processor than the 08M2 that I often use as my "master" controller. That's why I suggested additional commands: For example, being able to write complete "message" strings (to the EEPROM) is rather similar to hippy's proposal for a buffering mode. We would need to be careful not to "wear out" the EEPROM, but there's lots of spare (indirect) RAM in an 18M2.

Similarly, perhaps a "side-scroll" mode when each new character is received, or even "Display Date/Time" from an attached DS3231? As hippy implied, there are numerous possibilities and we can only provide the "hooks" for others to add features as they wish.

Cheers, Alan.
 

Circuit

Senior Member
I replaced the 18M2 on the AXE132 board with a PIC 16F1847 and ported the 18M2 firmware to ASM. Similar to what Rev-Ed did with the old FRM010 Firmware Chip (except that the baud was selectable at either 9600 or 38400 baud. 38400 gave a character rate of about 3,300 CPS which was acceptable. Consider that the display is capable of > 20,000 CPS.

Seems to me like Rev-ed might want to do something similar and offer its customers a firmware written in ASM or C that can speed up these very nice OLED displays.
Wow, what about offering this yourself? Many of us have the ability (and kit) to download firmware to a PIC even though we routinely use PICAXE because of its neat interface and effective programming language for many applications. I cannot imagine that anyone would object to you placing the hex code for this in one of the "finished projects" part of this forum - indeed I think many would be delighted and most grateful. Any chance?
 

julianE

Senior Member
I have used other driver chips for LCD driver, the source code is available free on PHAnderson site.

http://www.phanderson.com/lcd106/lcd107.html

I've used the preprogrammed chip but have not tried loading a raw PIC chip, I'm not sure if it will work with the OLED.

I was hesitant to mention this chip in case it competes with RevEd offering and if it's against forum rules please feel free to delete the post.
 

neiltechspec

Senior Member
Having something similar to this that runs at 4800 baud would be a bonus for me.
That way it can be used with sertxd on AXE's running at default 4Mhz.

Can't be that hard for Rev-Ed to do surely. Just the chip would do !.

Neil.
 

AllyCat

Senior Member
Hi,

The standard AXE133 firmware runs at 16 MHz (m16) so I think (but not yet tested) that setfreq m32 should give 4800 baud.

Yes, I'm also considering the use with SERTXD (that can easily be done already by changing the "host" to setfreq m2 of course) which is one reason why I'm attempting to support "control codes" like 13 and 10 (CR , LF) and others?

Cheers, Alan.
 

techElder

Well-known member
I'm also considering the use with SERTXD (that can easily be done already by changing the "host" to setfreq m2 of course)
Now we're getting somewhere interesting. Please explain further. I haven't had enough caffeine!
 

AllyCat

Senior Member
hi,

Now we're getting somewhere interesting. Please explain further. I haven't had enough caffeine!
SEROUT and SERTXD are very similar, but SERTXD has a default (fixed) baud rate proportional to the clock rate (I believe always 4800 baud at 4 MHz) and a fixed pin (the Serial Prograrmming output). The PICaxe manual says that both commands can't be used on the same pin, but there are exceptions (e.g. c.0 with an 08M2).

So it should be quite possible to connect the Serial Programming Output pin of any PICaxe to an AXE133. For a compatible baud rate, either the AXE133 clock could be increased to 32 MHz (setfreq m32) or the host/master PICaxe clock dropped to 2 MHz (m2). This could be applied just during the serial transmission and restored afterwards, if required.

I've also been considering a direct connection between the two programming sockets (including a "reply" path), but that requires a "crossed" cable (RXDs to TXDs). Also a change to the AXE133 firmware to DISCONNECT programming and accept serial data on the appropriate pin, and perhaps support additional control codes such as CR, LF.

Cheers, Alan.
 

stan74

Senior Member
Wow, what about offering this yourself? Many of us have the ability (and kit) to download firmware to a PIC even though we routinely use PICAXE because of its neat interface and effective programming language for many applications. I cannot imagine that anyone would object to you placing the hex code for this in one of the "finished projects" part of this forum - indeed I think many would be delighted and most grateful. Any chance?
I might be able to generate a hex file if you give me a basic file to convert or tell me what's required but this forum isn't the place really and if you have a programmer then you would program a pic yourself from posted code on the net. You can see my picaxe lcd graphic attempts in projects. Compare this to arduino line code which is almost instant and other oled displays like RE LED042. I remember using a DM1602F, the only one I didn't pull out of scrap gear and it was slow updating the display running off a pic.
 

matchbox

Senior Member
@AllyCat, I'm interested in whether you made any progress on this topic. Specifically the the ability to control DAC for OLED display lighting, via the 18M2, without it effecting the received serial data.
I even tried Hippy's idea, with a serin buffer. But had no luck with the terminator bit exiting the loop.

I'm working on a project that requires the main 28X2 to run at EM32Mhz, to perform all the tasks fast enough. While I also have to run the 18M2 @ 32Mhz 4800 as well.
I have skimmed the 18M2 serin, and it communicates fine at present. But I think adding the DAC OLED intensity level code would create too much latency and it would lose sync.

The reason that i'm even bothering with the 18M2 on the display. Is because I require it to be controlling the flashing and scrolling of characters, while the 28X2 is busy with other tasks.
 

AllyCat

Senior Member
Hi,

Yes, I have made some (personal) progress on various "AXE133/4" program features, but probably not in the directions that are particularly relevant to your application. However, you may need to explain in more detail how you plan to command and control the OLED Brightness (hardware and software). IMHO the "DAC" on most PIC(axe)s is so "limited" that it's not worth using (as a DAC output). Generally, low-pass filtering a PWM pin output (one R + C) is much more useful; just using a PWMOUT ..... (brightness range 0 - up to 1023) command, instead of a DACLEVEL (brightness range 0 -31).

In terms of sending (additional) "instructions" to the AXE133/4, I have come to the conclusion that it is essential for the sending PICaxe (or whatever else) to include a delay between each Byte / command. The only exception being "pure text" (i.e. Printable ASCIII characters being forwarded directly to the display controller chip), so that commands such as SEROUT ... ("Hello World") can be sent. However, even that will fail if using the 4-bit data bus mode (or I2C) to the LCD/OLED panel, or to one of the tiny SSD1306 OLED panels, which are (now) of more interest to me. My current (long-term) project if for an "AXE133/4 emulator" using a SSD1306/SH1106 controlled panel, with an "improved" command set (including Brightness and format commands, etc.).

To completely solve the issues of transfer speed, I will be using the HSERIN hardware , that effectively can run in the "background" (or with interrupts) using any of the M2 chips. However, there are a few restrictions: only a few HSERIN input pins are available on each chip, the hardware receives only "T" polarity (so a hardware inverter may be needed), and there are bugs in the PICaxe M2's HSERIN Command. I've discussed most of these details in various other threads on the forum, but won't list them all here now.

Cheers, Alan.
 

matchbox

Senior Member
Thanks for the reply Alan.
I am only using a 16 x 2 white OLED display I have had sitting around for a while. I have looked at the SSD1306. But would find it too small for this application. I want it viewable from farther away.

I'm not concerned about having a wide brightness control range. I figure that DAC should give me around 4 levels between min and full, which is ideal for my use. And I don't have a spare PWM pin. This project is using most of the 28X2's pins (Audio file player, RF module, RTC, 5 position switch, OLED display in 8bit, and the photo sensor). Its still a WIP and will be for a while.

The method I intend to use, is taking the ADC value from a photo transistor, then use some math to convert it to the required DAC range.
 

AllyCat

Senior Member
Hi,

A problem with the DAC output is its very high output impedance, which generally needs some form of buffer/amplifier. I assume(d) that the Brightness control / PWM would be from the 18M2, but do see that the only dedicated PWM pins are on Port B: The AXE133/4 reserving all the Port B pins (and more) to drive the OLED is quite a restriction, which is why I've been looking at alternative configurations. ;)

I don't know which method you plan to use to control the Brightness of the OLED, but the few spare "User" (Port C) pins on the AXE133/4 could carry a "Servo" width-modulated pulse, and/or do include a Comparator, and the S-R flip-flop outputs. Of course, the Brightness of the SSD1306 is controlled by a direct I2C command, which I why I plan to include a "Brightness" command in any new "Enhanced Interface". But I do agree that those tiny displays are too small for many purposes (but very compatible with some PICaxe projects).

Cheers, Alan.
 

matchbox

Senior Member
Hi again. I am planning on using the 18M2 on a AXE-133 to drive the OLED brightness. I certainty get your points, concerning the limitations. I don't really want to butcher the SMD AXE-133 board to use 4bit mode. So your idea of using a servo modulation pulse might work well. I will have to look into that.
The reason i'm asking about this now. Is so I can finish laying out the hardware, on some proven ideas from others. Before I spend more time working on the code features.
 

cpedw

Senior Member
I assume(d) that the Brightness control / PWM would be from the 18M2, but do see that the only dedicated PWM pins are on Port B: The AXE133/4 reserving all the Port B pins (and more) to drive the OLED is quite a restriction, which is why I've been looking at alternative configurations. ;)
Don't forget the Alternate Pin Function which easily allows a PWM output on C.7 (you told me about it this Spring, Alan). But perhaps SERVO will be simpler to use.

Derek
 

AllyCat

Senior Member
Hi,

Hmm, I've been looking in detail at the 18M2s facilities (which I never use myself, except on an assembled AXE133Y board) and see that I was wrong on two counts: The Comparator outputs are only available on the Programming (In/Out) pins, and Servo pulses are only available on Port B. :(

So the options are quite limited; I certainly wouldn't modify the board to 4-bit mode, but it might be worth "freeing up" pin C.7 to use the APFCON for "real" PWM on that pin. Otherwise, exact design details depend on the method of controlling the OLED Brightness, but probably an emitter follower (one external transistor) on the DAC output pin may be sufficient.

Or if you need only around 4 - 8 Brightness levels, then you might create a simple external "weighted resistors DAC" on the two or three "User" pins, which could have a much lower resistance than the 32 x 5k = 160k chain of the DAC. Tri-State might increase the capability to 3 analogue levels/pin, but I see that Weak Pullup resistors also are only available on Port B.

Cheers, Alan.
 
Top