Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 15:26 01 Jul 2025 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : Using internal RTCC on MM-28 chip.

Author Message
jwaldha
Newbie

Joined: 14/01/2016
Location: Hungary
Posts: 10
Posted: 06:18am 30 Mar 2016
Copy link to clipboard 
Print this post

I think the MM is very powerful tool.
For practice, I decided to making a battery-operated data logger.
Because the data logger operates from battery, must minimize the power consumption between the two measurements.
I want to store a measured datas together a timestamp.
Unfortunately in the SLEEP mode, the built-in clock is not working.
But, the microcontroller contains an RTCC periphery.
I think this would solve the exact timing.
(I know, it could be used an external RTCC circuit/module, but there is no challenge in that.)
The SOSC provide the 32.768KHz clock source for the internal RTCC using a "watch" crystal.
This crystal must connect to the chip 11, 12 pins.
Unfortunately, the 11, 12 pins already used by of the console connection. This prevents that the uses of internal RTCC.
I carefully studied the controller data sheets and documentation of MM, and I think I found a solution.

The trick PPS capability of the controller.

PPS broadly means that an internal peripheries of MCU has not fixed assignment to a dedicated pin,
but also in some peripheries can assign to member of a group of IC pins. (DataSheet 11.3).
The console uses the UART1. The UART1 must be to use 2 pins of IC.
(transmit & receive).
In the case of UART1 transmit, the following PPS assignments are available:

IC pin --- MM function --- MM firmware can overwrite
2 --- DIGITAL | ANALOG --- no
7 --- COM1: ENABLE | DIGITAL | ANALOG --- yes
11 --- CONSOLE Tx (DATA OUT) --- yes (reset)
16 --- DIGITAL | 5V | COUNT | WAKEUP | IR --- yes
26 --- ANALOG | DIGITAL | PWM 2A --- yes

For the receive:

IC pin --- MM function --- MM firmware can overwrite
6 --- PWM 1C | DIGITAL | ANALOG --- yes
9 --- COM2: TRANSMIT | DIGITAL --- no
12 --- CONSOLE Rx (DATA IN) --- yes (reset)
15 --- DIGITAL | 5V | COUNT --- yes
24 --- ANALOG | DIGITAL | PWM 2B --- yes

When uses the UART1 transmit and receive other than defaults pins,
then freed up the 11,12 pins, which is essential for using the SOSC!
I studied Geoff's the source code and revealed that the PPS feature is used in several places in the firmware.


Therefore, care must be taken not to use some MM commands after the remapped the UART1 pins,
which overwriting it. Otherwise, easy to exclude ourselves from the chip!
Potential conflicts:

PIN --- dangrous BASIC command
2 none
6 PWM 1,....
7 OPEN "COM1:....., DE...."
9 none
11 CPU RESTART, WATCHDOG...
12 CPU RESTART, WATCHDOG...
15 SETPIN 16, FIN|PIN|CIN
16 SETPIN 16, FIN|PIN|CIN
24 PWM 2,....
26 PWM 2,...

This does not mean that these pin can not be used only to proceed with caution!
The RTCC registers ( and the OSCCON) are protected against overwriting.
Only after a special sequence UNLOCK possible to write.

The specific tasks:
1. To free up the first 11,12 IC pins.
2. To solve to write the RTCC registers.
3. To write a function to initialize the RTCC.
I wrote CFUNTIONS to solve this three steps.
The CFUNCTIONs are only the most necessary to solve.
eg.: On the BASIC level must produce the correct format of the number,
that should be written in the RTC registers.
Since the every time when MCU resets the firmware set to the default value of PPS mappings,
it is appropriate to place the own PPS mappings in the MM.STARTUP subroutine.
So after each reset will return to their own setting.
CFunctions:

CFunction remapConsoleRX
00000000
8C820000 24030006 1443000B 8C840004 5480000A 24030009 3C02BF81 8C43FA50
24040004 7C831804 AC43FA50 24040001 10000032 00002821 24030009 5443000A
2403000C 54800008 2403000C 3C02BF81 8C43FA50 7C031804 AC43FA50 24040001
10000026 00002821 5443000B 2403000F 54800009 2403000F 3C02BF81 8C43FA50
24040002 7C831804 AC43FA50 24040001 1000001A 00002821 5443000B 24030018
54800009 24030018 3C02BF81 8C43FA50 24040001 7C831804 AC43FA50 24040001
1000000E 00002821 5443000B 00002021 54800009 00002021 3C02BF81 8C43FA50
24040003 7C831804 AC43FA50 24040001 10000002 00002821 00002821 00801021
03E00008 00A01821
End CFunction
'
CFunction remapConsoleTX
00000000
8C820000 24030002 1443000B 8C840004 5480000A 24030007 3C02BF81 8C43FB00
24040001 7C831804 AC43FB00 24040001 10000033 00002821 24030007 5443000B
2403000B 54800009 2403000B 3C02BF81 8C43FB38 24040001 7C831804 AC43FB38
24040001 10000026 00002821 5443000B 24030010 54800009 24030010 3C02BF81
8C43FB3C 24040001 7C831804 AC43FB3C 24040001 1000001A 00002821 5443000B
2403001A 54800009 2403001A 3C02BF81 8C43FB48 24040001 7C831804 AC43FB48
24040001 1000000E 00002821 5443000B 00002021 54800009 00002021 3C02BF81
8C43FB68 24040001 7C831804 AC43FB68 24040001 10000002 00002821 00002821
00801021 03E00008 00A01821
End CFunction
'
CSub startRTC
00000000
3C03BF81 3C02AA99 24426655 AC62F230 3C025566 344299AA AC62F230 3C02BF81
8C44F000 24050001 7CA40844 AC44F000 3C02BF80 8C440200 7CA418C4 AC440200
340580C8 3C04BF80 AC850200 8C440200 7C0418C4 AC440200 3C023333 24423333
AC62F230 03E00008 00000000
End CSub
'
CSub setRTCTime
00000000
3C03BF81 3C02AA99 24426655 AC62F230 3C025566 344299AA AC62F230 3C02BF80
8C450200 24060001 7CC518C4 AC450200 8C850000 3C04BF80 AC850220 8C440200
7C0418C4 AC440200 3C023333 24423333 AC62F230 03E00008 00000000
End CSub
'
CSub setRTCDate
00000000
3C03BF81 3C02AA99 24426655 AC62F230 3C025566 344299AA AC62F230 3C02BF80
8C450200 24060001 7CC518C4 AC450200 8C850000 3C04BF80 AC850230 8C440200
7C0418C4 AC440200 3C023333 24423333 AC62F230 03E00008 00000000
End CSub
'
CFunction getRTCTime
00000000
3C03BF80 8C620220 8C640220 1444FFFD 00000000 03E00008 00001821
End CFunction
'
CFunction getRTCDate
00000000
3C03BF80 8C620230 8C640230 1444FFFD 00000000 03E00008 00001821
End CFunction

BASIC interface:

Sub init
startRTC()
End Sub


Sub gettime
Local integer d, t
Local string s$
Local string year$, month$, day$, hour$, minute$, second$
s$ = Hex$(getRTCDate(), 8)
year$ = Left$(s$, 2)
month$ = Mid$(s$, 3, 2)
day$ = Mid$(s$, 5, 2)
Date$=day$ + "-" + month$ + "-20" + year$
s$ = Hex$(getRTCTime(), 8)
hour$ = Left$(s$, 2)
minute$ = Mid$(s$, 3, 2)
second$ = Mid$(s$, 5, 2)
Time$ = hour$ + ":" + minute$ + ":" + second$
End Sub

Sub settime(year%, month%, day%, hour%, minute%, second%)
Local string s$
Local integer dtmp, ttmp
s$ = Right$(Str$(year%, 4, 0, "0"),2)
s$ = s$ + Right$(Str$(month%, 2, 0, "0"), 2)
s$ = s$ + Right$(Str$(day%, 2, 0, "0"), 2)
dtmp = 0
For i=1 To Len(s$)
dtmp = dtmp << 4
dtmp = dtmp + Val(Mid$(s$, i, 1))
Next i
dtmp = dtmp << 8
s$ = Right$(Str$(hour%, 2, 0, "0"), 2)
s$ = s$ + Right$(Str$(minute%, 2, 0, "0"), 2)
s$ = s$ + Right$(Str$(second%, 2, 0, "0"), 2)
ttmp = 0
For i=1 To Len(s$)
ttmp = ttmp << 4
ttmp = ttmp + Val(Mid$(s, i, 1))
Next i
ttmp = ttmp << 8
setRTCTime(ttmp)
setRTCDate(dtmp)
End Sub


Sub mm.startup
if remapConsoleTX(7) = 0 then
' Unsuccessfull mapping. Restart MCU
watchdog 1
endif
if remapConsoleRX(6) = 0 then
' Unsuccessfull mapping. Restart MCU
watchdog 1
endif
Print "MM started with remapped console."
Print " ConsoleRx - 6"
Print " ConsoleTx - 7"
End Sub

BASIC example:

MM started with remapped console:
RX -> pin 6
TX -> pin 7
> init
> settime 2016,3,30,17,56,25
> gettime : ? date$, time$
30-03-2016 17:56:34
> ? time$ : cpu sleep 3 : ? time$ : gettime : ? time$
17:56:55
17:56:55
17:56:58
>

C source code:

#define _SUPPRESS_PLIB_WARNING
#include <plib.h>
#include "CFunctions.h"


/*
U1TX:
2 RPA0 PPSOutput(1, RPA0, U1TX); DIGITAL | ANALOG
7 RPB3 PPSOutput(1, RPB3, U1TX); COM1: ENABLE | DIGITAL | ANALOG
11 RPB4 PPSOutput(1, RPB4, U1TX); CONSOLE Tx (DATA OUT)
16 RPB7 PPSOutput(1, RPB7, U1TX); DIGITAL | 5V | COUNT | WAKEUP | IR
26 RPB15 PPSOutput(1, RPB15, U1TX); ANALOG | DIGITAL | PWM 2A


U1RX:
6 RPB2 PPSInput(3, U1RX, RPB2); PWM 1C | DIGITAL | ANALOG
9 RPA2 PPSInput(3, U1RX, RPA2); COM2: TRANSMIT | DIGITAL
12 RPA4 PPSInput(3, U1RX, RPA4); CONSOLE Rx (DATA IN)
15 RPB6 PPSInput(3, U1RX, RPB6); DIGITAL | 5V | COUNT
24 RPB13 PPSInput(3, U1RX, RPB13); ANALOG | DIGITAL | PWM 2B



*/
long long remapConsoleRX(long long *pin) {
if (*pin == 6) {
PPSInput(3, U1RX, RPB2); // PWM 1C | DIGITAL | ANALOG
// interfere with PWM 1,....
return 1;
}
if (*pin == 9) {
PPSInput(3, U1RX, RPA2); // COM2: TRANSMIT | DIGITAL
return 1;
}
if (*pin == 12) {
PPSInput(3, U1RX, RPA4); // CONSOLE Rx (DATA IN)
// The default Console pin
return 1;
}
if (*pin == 15) {
PPSInput(3, U1RX, RPB6); // DIGITAL | 5V | COUNT
// interfere with SETPIN 16, FIN|PIN|CIN
return 1;
}
if (*pin == 24) {
PPSInput(3, U1RX, RPB13); // ANALOG | DIGITAL | PWM 2B
// interfere with PWM 2,....
return 1;
}
return 0;
}

long long remapConsoleTX(long long *pin) {
if (*pin == 2) {
PPSOutput(1, RPA0, U1TX); // DIGITAL | ANALOG
return 1;
}
if (*pin == 7) {
PPSOutput(1, RPB3, U1TX); // COM1: ENABLE | DIGITAL | ANALOG
// interfere with OPEN "COM1:....., DE...."
return 1;
}
if (*pin == 11) {
PPSOutput(1, RPB4, U1TX); // CONSOLE Tx (DATA OUT)
// The default Console pin.
return 1;
}
if (*pin == 16) {
PPSOutput(1, RPB7, U1TX); // DIGITAL | 5V | COUNT | WAKEUP | IR
// interfere with SETPIN 16, FIN|PIN|CIN
return 1;
}
if (*pin == 26) {
PPSOutput(1, RPB15, U1TX); // ANALOG | DIGITAL | PWM 2A
// interfere with PWM 2,...
return 1;
}
return 0;
}


void startRTC(void) {
SYSKEY = 0xAA996655;
SYSKEY = 0x556699AA;
OSCCONbits.SOSCEN = 1; // Start SOSC
RTCCONbits.RTCWREN = 1; // Enable RTC registers write
RTCCON = 0x80C8;
RTCCONbits.RTCWREN = 0; // Disable RTC registers write
SYSKEY = 0x33333333;
}


void setRTCTime(long long *param) {
SYSKEY = 0xAA996655;
SYSKEY = 0x556699AA;
RTCCONbits.RTCWREN = 1;
RTCTIME = *param;
RTCCONbits.RTCWREN = 0;
SYSKEY = 0x33333333;
}

void setRTCDate(long long *param) {
SYSKEY = 0xAA996655;
SYSKEY = 0x556699AA;
RTCCONbits.RTCWREN = 1;
RTCDATE = *param;
RTCCONbits.RTCWREN = 0;
SYSKEY = 0x33333333;
}

long long getRTCTime(void) {
unsigned int t1, t2;
do {
t1 = RTCTIME;
t2 = RTCTIME;
} while (t1 != t2);
return t1;
}

long long getRTCDate(void) {
unsigned int d1, d2;
do {
d1 = RTCDATE;
d2 = RTCDATE;
} while (d1 != d2);
return d1;
}


void main(void) {}


Ps.:
I apologize for any errors in the language!


---
JWaldha
 
drkl

Senior Member

Joined: 18/10/2015
Location: Hungary
Posts: 102
Posted: 08:13am 30 Mar 2016
Copy link to clipboard 
Print this post

Hello János,
Congratulate, good works.
I'll test it...

drkl
 
Geoffg

Guru

Joined: 06/06/2011
Location: Australia
Posts: 3281
Posted: 11:13am 30 Mar 2016
Copy link to clipboard 
Print this post

Wow, that is an amazingly complete solution.
Welcome to the forum and what a debut!!

I considered using the internal PIC32 RTC in MMBasic but I figured that it was simpler for most people to use an external RTC. However, it would be nice for users to still have the option of using the internal RTC and this does exactly that. Congratulations.

You have obviously mastered CFunctions which is not easy... congratulations again.

Geoff
Geoff Graham - http://geoffg.net
 
Print this page


To reply to this topic, you need to log in.

The Back Shed's forum code is written, and hosted, in Australia.
© JAQ Software 2025