After the big victory of getting a bright blue digit working, and the lesser victory of getting the RTC chip communication working, plus some time away from home, I’ve been stalled on the clock for a while. I gave myself a kickstart yesterday by connecting both the DS1302 timekeeping chip and the one-digit display at the same time, and writing some demo code to flash the current hour and minute one digit at a time.
Enough Controller Pins
I had written previously about whether I was going to have enough pins on the controller to run all the different lines I need to hook up. Now that I’m a little further along in development (working prototypes of different parts, settled on the choice of RTC chip), I think I’ve nailed down the exact pinouts I’m going to use:
Pins |
Subsystem |
Signals |
Function / Notes |
|
A0 |
RTC |
CE |
enable |
A1 |
RTC |
I/O |
I/O |
A2 |
RTC |
SCLK |
data clock |
A3-5 |
unused |
. |
. |
|
B0 |
display |
SDI |
data input (to display) |
B1 |
display |
CK |
data clock |
B2-7 |
display |
L0-5 |
data latches for six digits |
|
C2 |
display |
/OE |
display enable PWM output for software dimming of display |
|
C6 |
UART |
TX |
transmit |
C7 |
UART |
RX |
receive |
It seems positively serendipitous that I’m able to use the built-in UART for time synchronization and the one free PWM output for software display dimming without overriding any of the LogoChip’s firmware functions, and everything still fits. I even have a few pins left over, if I think of something else I need to add.
Port A and Analog Inputs
I’d had trouble using A0-2 to control the A6276, and Muaz (in a comment) and I both assumed it must have something to do with the analog inputs (even though I was only outputting to the pins). Looking over the PIC18F2220/2320/4220/4320 datasheet, I can’t find any reason for that–when the pins are set for output, they’re simply outputs like any other pins (although the A/D converter is available at any time, so you can always measure the actual voltage on the port regardless of mode or direction–how curious).
However, since I’ve now moved the RTC to port A (so port B can be used contiguously to drive the display), I needed to be able to use the pins as digital inputs; and I was pretty sure they were configured for A/D when in input mode.
Indeed, the LogoChip language reference says that pins A0-3 and A5 are configured as analog inputs on boot. So I studied the PIC datasheet and wrote a function to configure them as analog or digital as desired. I had guessed that there’d be a bit-wise control register like the I/O port tristate registers; but in fact, there’s a register nybble that simply contains a count of how many analog ports you want; and the PIC makes the right number of ports analog in order from the list A0, A1, A2, A3, A5, E0, E1, E1, B2, B3, B1, B4, B0 (with the E ports only available on 4×20 chips); which is kind of a clever way of doing things.
Here’s my library routine:
- ad.lib – Library routine to set number of analog inputs
Here’s the code:
; Keith Neufeld
; 05-Aug-2006
;
; LogoChip library to configure the number of analog inputs, which
; start on port A and work into port E (on the 4320) and port B:
;
; A0, A1, A2, A3, A5, E0, E1, E1, B2, B3, B1, B4, B0
;
; (PIC18F2220/2320/4220/4320 Datasheet, p. 4)
;
; Lines set as analog inputs also function as digital outputs,
; depending on the settings of their port's tristate register. Lines
; not set as analog inputs function as digital I/O.
;
; The PIC sets all possible inputs to analog on powerup (Datasheet
; p. 50), which the LogoChip firmware overrides to five (A0-3 and A5;
; LogoChip Language Reference, p. 7).
constants [
[ADCON $fc1] ; port A control register
[PCFG-MASK #00001111] ; mask for port config bits
; Datasheet p. 214
]
to config-analog-lines :number
if (:number < 0 or :number > 13) [ ; only 13 lines possible
stop
]
; Preserve high nybble and set low nybble to %1111 minus the desired
; number of analog lines.
;
; *ADCON = (*ADCON & !PCFG-MASK) | (PCFG-MASK - :number)
write ADCON (((read ADCON) and (not PCFG-MASK)) or (PCFG-MASK - :number))
end
I told a little fib–the PCFG (port config) nybble actually contains the bitwise inverse of the number of lines configured as analog, as the code shows.
Integration
So . . . I set the PIC for 0 analog inputs, moved the DS1302 interface to A0-2, and it still works fine. Glommed together the demo code for the DS1302 and one-digit display:
constants [
[spew-on-msec 200] [spew-off-msec 30]
]
to ds1302-a6276-time
ds1302-read-clock
a6276-display-digit nybble-high ds1302-get-hour 0 0
mwait spew-on-msec
a6276-off
mwait spew-off-msec
a6276-display-digit nybble-low ds1302-get-hour 0 0
mwait spew-on-msec
a6276-off
mwait spew-off-msec
[. . .]
a6276-display-digit nybble-high ds1302-get-minute 0 0
[. . .]
a6276-display-digit nybble-low ds1302-get-minute 0 0
[. . .]
And I now have a nice little demo which, upon power on, flashes the digits of HH:MM up onto my display, one at a time, with no host computer attached. Perfect.
It’s a little hard for me to read the digits in the video, due to some combination of my wireless connection, the persistence of my PowerBook LCD, and the low CPU power. But I tweaked the timing pretty carefully to make sure each digit displays long enough to register what I just saw, and that the inter-digit blanking is long enough to distinguish repeated digits. (I want the digits to flash fast, but I’m not trying to build a persistence of vision project.) It looks pretty good on my wife’s PC where I dock the camera to upload and preview the video clips, so I hope the web video okay for everyone but me.
Code Cleanup
Right now, I have DS1302 and A6276 code split off into separate libraries (good), but the actual port pins hardcoded into the libraries (bad). That means when I change my mind about where to plug something in, I have to edit the library code–and that means if I’m using the library for more than one project, I just broke the other programs, so it’s not really a library.
What I really need, linguistically speaking, is lambdas–the ability for a function to return an anonymous function (or function pointer) that has parameters of the generator function coded into the returned function as constants. That is, I’d call
setrtcfunc ds1302-init porta 0 porta 1 porta 2
and now rtcfunc
contains a function I can use to access the DS1302 that’s on A0-2.
Aw, heck, I admit what I really need here is an object generator and to use method calls against it to perform further operations; but I hate OO faddists and would much rather sound cool talking about functional languages.
At any rate, much to my surprise, :-^ LogoChip Logo doesn’t support any of those things. So I’ll settle for only being able to use one DS1302 per PIC (which for me is like, uh, pretty realistic); and I need to write an init routine to stuff the port selections into local (er, global) variables so the library is really general-purpose again. But that means putting code into all the function calls to make sure that the port selection has been initialized and aborting if not, and that means deciding whether/how to alert the caller that something went wrong, and that means more thinking, and I’m not so much in a thinking mood right now.
I’m Waiting On . . .
I have a MAX232 RS-232 line-level driver on the way to interface the PIC’s UART to the PC. Once I get that, I’ll breadboard it, write proof-of-concept code to show that I can make the PIC talk to a PC without the LogoChip halting its program to listen (like it does on the LogoChip’s software-based communications and reprogramming port) so I can later write PC time synchronization code. Then I’m ready to lay out the daughterboard for the controller, W00T!
I’m still fussing with expanding the single-digit display into the full six-digit. I made the single-digit display with only a single latch line (and I need one for each digit of the full display) and power traces that are totally inadequate for the ~4A the full display is going to draw. I’ve cloned the digit six times over on the schematic, but haven’t finished touching up the latch and power lines.
And then I’m going to have to learn FreePCB, because EAGLE Free/Light only does boards up to 80x100mm (~3.2×4″) and even EAGLE Standard ($200 each for the circuit design and board layout modules???) only does 160x100mm (~6.3×4″); so I’d have to go up to EAGLE Pro ($400 each for design and layout?!!), and that ain’t gonna happen.
Time to learn FreePCB, which costs $0, makes boards up to 60×60″, recommends using EAGLE for circuit design and export . . . and only runs on Windows. Sigh.