diff --git a/G0:G070/RTC/README b/G0:G070/RTC/README index 351b779..c977189 100644 --- a/G0:G070/RTC/README +++ b/G0:G070/RTC/README @@ -2,9 +2,11 @@ Simplest work with RTC Proto: +C - set/print calibration ticks (-511..+512) to each 2^20 ticks +Sd - set date (YY MM DD Weekday) +St - set time (HH MM SS) t - print current Tms -T - print current Time like 'Mon Jan 1 00:05:19 2001' - +T - print current Time Button press - print current time @ usart3 diff --git a/G0:G070/RTC/main.c b/G0:G070/RTC/main.c index e680532..6c2c9da 100644 --- a/G0:G070/RTC/main.c +++ b/G0:G070/RTC/main.c @@ -65,7 +65,7 @@ int main(void){ int wasbo = 0; char *rcv = usart3_getline(&wasbo); if(wasbo) usart3_sendstr("Buffer overflow occured @ last message\n"); - if(rcv) rcv = parse_cmd(rcv); + if(rcv) rcv = (char*)parse_cmd(rcv); if(rcv) usart3_sendstr(rcv); } } diff --git a/G0:G070/RTC/proto.c b/G0:G070/RTC/proto.c index dca5aac..3365901 100644 --- a/G0:G070/RTC/proto.c +++ b/G0:G070/RTC/proto.c @@ -26,6 +26,9 @@ extern volatile uint32_t Tms; const char *helpstring = + "C - set/print calibration ticks (-511..+512) to each 2^20 ticks\n" + "Sd - set date (YY MM DD Weekday)\n" + "St - set time (HH MM SS)\n" "t - print current Tms\n" "T - print current Time\n" ; @@ -36,6 +39,7 @@ TRUE_INLINE void putch(char x){ static const char *weekdays[] = {"Mon", "Tue", "Wed", "Thur", "Fri", "Sat", "Sun"}; static const char *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "June", "July", "Aug", "Sept", "Oct", "Nov", "Dec"}; +static const char *OK = "OK\n"; static void prezero(uint8_t x){ if(x < 10){ putch('0'); putch('0' + x);} @@ -45,7 +49,7 @@ static void prezero(uint8_t x){ void print_curtime(){ rtc_t t; get_curtime(&t); - USND(weekdays[t.day - 1]); + USND(weekdays[t.weekday - 1]); putch(' '); USND(months[t.month - 1]); putch(' '); @@ -60,13 +64,75 @@ void print_curtime(){ putch('\n'); } -char *parse_cmd(char *buf){ - // "long" commands -/* switch(*buf){ - }*/ - // "short" commands - if(buf[1]) return buf; // echo wrong data +static int readNu8(const char *buf, uint8_t *arr, int maxlen){ + uint32_t D; + const char *nxt; + int N = 0; + while((nxt = getnum(buf, &D)) && nxt != buf && N < maxlen){ + buf = nxt; + if(D > 0xff){ + USND("Value too large\n"); + return N; + } + arr[N++] = (uint8_t) D&0xff; + } + return N; +} + +TRUE_INLINE const char* setdatetime(const char *buf){ + buf = omit_spaces(buf); + uint8_t array[4]; + rtc_t r; switch(*buf){ + case 'd': // set date + if(4 != readNu8(buf+1, array, 4)) + return "Format: YY MM DD Weekday (monday is 1)\n"; + r.year = array[0]; + r.month = array[1]; + r.day = array[2]; + r.weekday = array[3]; + if(!rtc_setdate(&r)) return "Wrong date format\n"; + break; + case 't': // set time + if(3 != readNu8(buf+1, array, 3)) + return "Format: HH MM SS\n"; + r.hour = array[0]; + r.minute = array[1]; + r.second = array[2]; + if(!rtc_settime(&r)) return "Wrong time format\n"; + break; + default: + return "Sd -> set date; St -> set time\n"; + } + return OK; +} + +TRUE_INLINE const char *setcal(const char *buf){ + int32_t v; + if(buf == getint(buf, &v)){ + USND("Calibration value: "); + USND(i2str(rtc_getcalib())); + putch('\n'); + return NULL; + } + if(!rtc_setcalib(v)) return "Enter value: -511..+512\n"; + return OK; +} + +const char *parse_cmd(char *buf){ + const char *x = omit_spaces(buf); + // "long" commands + switch(*x){ + case 'S': + return setdatetime(x + 1); + break; + case 'C': + return setcal(x + 1); + break; + } + // "short" commands + if(x[1]) return x; // echo wrong data + switch(*x){ case 't': USND("T="); USND(u2str(Tms)); diff --git a/G0:G070/RTC/proto.h b/G0:G070/RTC/proto.h index a39fa1f..88207a2 100644 --- a/G0:G070/RTC/proto.h +++ b/G0:G070/RTC/proto.h @@ -18,5 +18,5 @@ #pragma once -char *parse_cmd(char *buf); +const char *parse_cmd(char *buf); void print_curtime(); diff --git a/G0:G070/RTC/rtc.bin b/G0:G070/RTC/rtc.bin index 10bc3ba..0bb1fae 100755 Binary files a/G0:G070/RTC/rtc.bin and b/G0:G070/RTC/rtc.bin differ diff --git a/G0:G070/RTC/rtc.c b/G0:G070/RTC/rtc.c index 541d103..8ba2c06 100644 --- a/G0:G070/RTC/rtc.c +++ b/G0:G070/RTC/rtc.c @@ -24,6 +24,56 @@ #define WAITWHILE(x) do{register uint32_t StartUpCounter = 0; while((x) && (++StartUpCounter < 0xffffff)){nop();}}while(0) #endif +static const uint8_t maxdays[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + +// i - in, r - rest of divide +#if 0 +static uint16_t div10s(uint16_t i, uint16_t *r){ // divide by 10 + uint32_t u = i; + u *= 52429; + u >>= 19; + if(r) *r = i - 10*u; + return (uint16_t)u; +} +#endif +static uint8_t div10b(uint8_t i, uint8_t *r){ // divide by 10 + uint32_t u = i; + u *= 52429; + u >>= 19; + if(r) *r = i - 10*u; + return (uint8_t)u; +} + +static uint8_t DEC2BCD(uint8_t x){ + uint8_t d, r; + d = div10b(x, &r); + return (d << 4 | r); +} + +int rtc_setdate(rtc_t *d){ + if(d->year > 99) return FALSE; + if(d->month > 12 || d->month == 0) return FALSE; + if(d->day > maxdays[d->month - 1] || d->day == 0) return FALSE; + if(d->month == 2 && d->day == 29 && (d->year & 4) != 4) return FALSE; // not leap year + if(d->weekday > 7 || d->weekday == 0) return FALSE; + RTC->ICSR |= RTC_ICSR_INIT; + WAITWHILE(!(RTC->ICSR & RTC_ICSR_INITF)); + RTC->DR = DEC2BCD(d->year) << RTC_DR_YU_Pos | d->weekday << RTC_DR_WDU_Pos | DEC2BCD(d->month) << RTC_DR_MU_Pos | DEC2BCD(d->day) << RTC_DR_DU_Pos; + RTC->ICSR &= ~RTC_ICSR_INIT; + return TRUE; +} + +int rtc_settime(rtc_t *t){ + if(t->hour > 23) return FALSE; + if(t->minute > 59) return FALSE; + if(t->second > 59) return FALSE; + RTC->ICSR |= RTC_ICSR_INIT; + WAITWHILE(!(RTC->ICSR & RTC_ICSR_INITF)); + RTC->TR = DEC2BCD(t->hour) << RTC_TR_HU_Pos | DEC2BCD(t->minute) << RTC_TR_MNU_Pos | DEC2BCD(t->second) << RTC_TR_SU_Pos; + RTC->ICSR &= ~RTC_ICSR_INIT; + return TRUE; +} + void rtc_setup(){ PWR->CR1 |= PWR_CR1_DBP; // disable RTC write protection // turn on LSE and switch RTC to it @@ -59,3 +109,25 @@ void get_curtime(rtc_t *t){ t->weekday = (r >> RTC_DR_WDU_Pos) & 0x7; t->year = BCDu(RTC_DR_YU_Pos) + 10 * BCDu(RTC_DR_YT_Pos); } + +// set calibration value +int rtc_setcalib(int calval){ + if(calval < -511 || calval > 512) return FALSE; + uint32_t calp = 0, calm = 0; + if(calval < 0) calm = -calval; + else if(calval > 0){ + calp = RTC_CALR_CALP; + calm = 512 - calval; + } + // unlock RCC + RTC->WPR = 0xCA; + RTC->WPR = 0x53; + RTC->CALR = calp | calm; + return 1; +} + +int rtc_getcalib(){ + int calval = (RTC->CALR & RTC_CALR_CALP) ? 512 : 0; + calval -= RTC->CALR & 0x1ff; + return calval; +} diff --git a/G0:G070/RTC/rtc.h b/G0:G070/RTC/rtc.h index e5f8c8c..81f695a 100644 --- a/G0:G070/RTC/rtc.h +++ b/G0:G070/RTC/rtc.h @@ -34,3 +34,7 @@ typedef struct{ void rtc_setup(); void get_curtime(rtc_t *t); +int rtc_setdate(rtc_t *d); +int rtc_settime(rtc_t *t); +int rtc_setcalib(int calval); +int rtc_getcalib(); \ No newline at end of file diff --git a/G0:G070/RTC/strfunc.c b/G0:G070/RTC/strfunc.c index c52785e..89b898b 100644 --- a/G0:G070/RTC/strfunc.c +++ b/G0:G070/RTC/strfunc.c @@ -60,8 +60,11 @@ static char *_2str(uint32_t val, uint8_t minus){ *(--bufptr) = '0'; }else{ while(val){ - *(--bufptr) = val % 10 + '0'; - val /= 10; + uint32_t x = val / 10; + *(--bufptr) = (val - 10*x) + '0'; + val = x; + //*(--bufptr) = val % 10 + '0'; + //val /= 10; } } if(minus) *(--bufptr) = '-'; @@ -113,12 +116,12 @@ char *uhex2str(uint32_t val){ * @param buf - string * @return - pointer to first character in `buf` > ' ' */ -char *omit_spaces(const char *buf){ +const char *omit_spaces(const char *buf){ while(*buf){ if(*buf > ' ') break; ++buf; } - return (char*)buf; + return buf; } /** @@ -127,7 +130,7 @@ char *omit_spaces(const char *buf){ * @param N - number read * @return Next non-number symbol. In case of overflow return `buf` and N==0xffffffff */ -static char *getdec(const char *buf, uint32_t *N){ +static const char *getdec(const char *buf, uint32_t *N){ char *start = (char*)buf; uint32_t num = 0; while(*buf){ @@ -144,11 +147,11 @@ static char *getdec(const char *buf, uint32_t *N){ ++buf; } *N = num; - return (char*)buf; + return buf; } // read hexadecimal number (without 0x prefix!) -static char *gethex(const char *buf, uint32_t *N){ - char *start = (char*)buf; +static const char *gethex(const char *buf, uint32_t *N){ + const char *start = buf; uint32_t num = 0; while(*buf){ char c = *buf; @@ -173,11 +176,11 @@ static char *gethex(const char *buf, uint32_t *N){ ++buf; } *N = num; - return (char*)buf; + return buf; } // read octal number (without 0 prefix!) -static char *getoct(const char *buf, uint32_t *N){ - char *start = (char*)buf; +static const char *getoct(const char *buf, uint32_t *N){ + const char *start = (char*)buf; uint32_t num = 0; while(*buf){ char c = *buf; @@ -193,11 +196,11 @@ static char *getoct(const char *buf, uint32_t *N){ ++buf; } *N = num; - return (char*)buf; + return buf; } // read binary number (without b prefix!) -static char *getbin(const char *buf, uint32_t *N){ - char *start = (char*)buf; +static const char *getbin(const char *buf, uint32_t *N){ + const char *start = (char*)buf; uint32_t num = 0; while(*buf){ char c = *buf; @@ -213,7 +216,7 @@ static char *getbin(const char *buf, uint32_t *N){ ++buf; } *N = num; - return (char*)buf; + return buf; } /** @@ -223,9 +226,9 @@ static char *getbin(const char *buf, uint32_t *N){ * @return pointer to first non-number symbol in buf * (if it is == buf, there's no number or if *N==0xffffffff there was overflow) */ -char *getnum(const char *txt, uint32_t *N){ - char *nxt = NULL; - char *s = omit_spaces(txt); +const char *getnum(const char *txt, uint32_t *N){ + const char *nxt = NULL; + const char *s = omit_spaces(txt); if(*s == '0'){ // hex, oct or 0 if(s[1] == 'x' || s[1] == 'X'){ // hex nxt = gethex(s+2, N); @@ -247,6 +250,22 @@ char *getnum(const char *txt, uint32_t *N){ return nxt; } +// get signed integer +const char *getint(const char *txt, int32_t *I){ + const char *s = omit_spaces(txt); + int32_t sign = 1; + uint32_t U; + if(*s == '-'){ + sign = -1; + ++s; + } + const char *nxt = getnum(s, &U); + if(nxt == s) return txt; + if(U & 0x80000000) return txt; // overfull + *I = sign * (int32_t)U; + return nxt; +} + /* void mymemcpy(char *dest, const char *src, int len){ if(len < 1) return; diff --git a/G0:G070/RTC/strfunc.h b/G0:G070/RTC/strfunc.h index a6662d5..cdb27b5 100644 --- a/G0:G070/RTC/strfunc.h +++ b/G0:G070/RTC/strfunc.h @@ -21,9 +21,10 @@ #include void hexdump(int (*sendfun)(const char *s), uint8_t *arr, uint16_t len); -char *u2str(uint32_t val); -char *i2str(int32_t i); -char *uhex2str(uint32_t val); -char *getnum(const char *txt, uint32_t *N); -char *omit_spaces(const char *buf); +const char *u2str(uint32_t val); +const char *i2str(int32_t i); +const char *uhex2str(uint32_t val); +const char *getnum(const char *txt, uint32_t *N); +const char *omit_spaces(const char *buf); +const char *getint(const char *txt, int32_t *I); //void mymemcpy(char *dest, const char *src, int len);