* grid. Grid 1 an 2 have an additional dot that can be set */
int set_grid(uint8_t offset, char value, bool dot) {
- //int (*ack)() = ack_recv; /* Scary function pointer :D */
if (offset > 3) {
printf("Offset incorrect");
tm1637_reset();
+
+ int (*ack)() = &ack_recv;
+ if ((((value >> 4) & 0xF) == 0xF ) && !(value & 0x08)) {
+ ack = &ack10_recv;
+ }
+
/* Write value to segments */
start_condition();
rwrite(I2C_DR, value);
- if(!ack_recv())
- return -1;
- stop_condition();
+ if(!ack()) {
+ // return -1;
+ }
+ stop_condition();
+ delay(); // wait for the chip to finish writing
tm1637_reset();
return 0;
return -1;
}
stop_condition();
-
tm1637_reset();
return 0;
-
}
-
void tm1637_example() {
-unsigned char display_number[10] = {0xFC, 0x60, 0xDA, 0xF2, 0x66, 0xB6, 0xBE, 0xE0, 0xFE, 0xF6};
-
-
+ unsigned char dn[10] = {0xFC, 0x60, 0xDA, 0xF2, 0x66, 0xB6, 0xBE, 0xE0, 0xFE, 0xF6};
char love[4] = { 0x1C, 0xFC, 0x7C, 0x9E };
-
+
for (int i = 0; i < 4; i++) {
set_grid(i, love[i], NODOT);
}
- set_display(true, 0);
-
}
/* HELPER ROUTINES */
}
+/* Write delay chip */
+static void delay() {
+ int a = 0;
+ for (int i = 0; i < 500; i++)
+ a++;
+}
+
+
/* Check if lines are idle (i.e. stop condition finished)*/
int idle() {
int cnt = 0;
/* (CC-BY-NC-SA) ROBIN KRENS - ROBIN @ ROBINKRENS.NL
*
* $LOG$
- * 2019/7/30 - ROBIN KRENS
+ * 2019/8/14 - ROBIN KRENS
* Initial version
*
* $DESCRIPTION$
+ * Real Time Clock configuration. A Real Time Clock is configured to use
+ * the more accurate external chrystal (LSE) and ticks at exactly
+ * one second. (Can be further calibrated using a tamper pin)
+ * Each clock tick triggers an interrupt and invokes the real time clock
+ * service routine.
+ *
+ * Note: this is not the Cortex M3/M4 SysTick!
*
* */
#include <sys/mmap.h>
#include <lib/regfunc.h>
-#include <lib/stdio.h>
+#include <lib/tinyprintf.h>
#include <drivers/led.h>
+#include <drivers/tm1637.h>
-static void periodic_intr() {
+/* This handler is invoked each clock tick. I've included two examples
+ * one is writing the clock count to a 4 grid led display. Another is a simple LED blink */
+void * rtc_handler() {
- while(!rchkbit(RTC_CRL, 5)); // Check last write is terminated
- rsetbit(RTC_CRL, 4); // start configure
-
- rsetbit(RTC_CRH, 0); // enable periodic (second) interrupt
-
- while(!rchkbit(RTC_CRL, 5));
+ // Real time clock output on a LED display
+ int cntvalue = *RTC_CNTL;
+ if (cntvalue < 9999) {
- rwrite(RTC_PRLL, 0x7FFF); // 1 second
- rclrbit(RTC_CRL, 4); // stop configure
- while(!rchkbit(RTC_CRL, 5)); // Check last write is terminated
- rsetbit(NVIC_ISER0, 3); // enable in register vector
-}
+ unsigned char dn[10] = {0xFC, 0x60, 0xDA, 0xF2, 0x66, 0xB6, 0xBE, 0xE0, 0xFE, 0xF6};
+
+ int grid0, grid1, grid2, grid3;
-static void calibrate_rtc() {
+ grid0 = cntvalue % 10;
+ grid1 = ((cntvalue % 100) - grid0) / 10;
+ grid2 = ((cntvalue % 1000) - grid0 - grid1) / 100;
+ grid3 = ((cntvalue % 10000) - grid0 - grid1 - grid2) / 1000;
+ printf("%d, %d, %d, %d\n", grid0, grid1, grid2, grid3);
+
+
+ char current[4] = { dn[grid3], dn[grid2], dn[grid1], dn[grid0] };
-// rsetbit(BKP_RTCCR, 7); // enable CC0,
-// while(!rchkbit(RTC_CRL, 5)); // Check last write is terminated
-// rsetbit(RTC_CRL, 4);
+ //char current[4] = { dn[1], dn[1], dn[1], dn[1] };
+ for (int i = 0; i < 4; i++) {
+ set_grid(i, current[i], false);
+ }
- // Set up and check tamper pin
+ set_display(true, 0);
-// rclrbit(RTC_CRL, 4);
-// while(!rchkbit(RTC_CRL, 5)); // Check last write is terminated
-}
-
-void * rtc_handler() {
+ }
- //cputs("TICKING IN REAL TIME\n");
+ // Simple LED blink
//uint32_t curr = *RTC_CNTL;
- int even = *RTC_CNTL % 2;
- (!even) ? led_off() : led_on();
+ //int even = *RTC_CNTL % 2;
+ //(!even) ? led_off() : led_on();
- rclrbit(RTC_CRL, 0);
+ rclrbit(RTC_CRL, 0); /* clear interrupt flag */
}
+/* Enable a periodic interrupt. At each clock count a interrupt is triggered
+ * and consequently the handler is invoked. */
+static void periodic_intr() {
+
+ while(!rchkbit(RTC_CRL, 5)); // Check last write is terminated
+ rsetbit(RTC_CRL, 4); // start configure
+ rsetbit(RTC_CRH, 0); // enable periodic (second) interrupt
+
+ while(!rchkbit(RTC_CRL, 5));
+ rwrite(RTC_PRLL, 0x7FFF); // 0x7FFF equals 1 second clock configuration
+ rclrbit(RTC_CRL, 4); // stop configure
+ while(!rchkbit(RTC_CRL, 5)); // Check last write is terminated
+ rsetbit(NVIC_ISER0, 3); // enable in register vector
+}
+
+/* Setup the Real time clock to work with the Low speed external
+ * chrystal (32.768 kHz) */
static void setup_rtc() {
-// TODO: long time to get stable?
/* Enable PWREN and BKPEN */
rsetbit(RCC_APB1ENR, 28);
rsetbit(RCC_APB1ENR, 27);
ivt_set_gate(19, rtc_handler, 0); /* setup interrupt handler */
-// calibrate_rtc(); TODO: TAMPER PIN?
+ //calibrate_rtc(); // uncomment if need, needs TAMPER PIN
periodic_intr();// setup periodic interrupt
}
+/* Function to calibrate the RTC even more accurate.
+ * Output to a so-called tamper pin. Uncomment if needed */
+static void calibrate_rtc() {
+ /* rsetbit(BKP_RTCCR, 7); // enable CC0,
+ while(!rchkbit(RTC_CRL, 5)); // Check last write is terminated
+ rsetbit(RTC_CRL, 4);
+ // Set up and check tamper pin
+ rclrbit(RTC_CRL, 4);
+ while(!rchkbit(RTC_CRL, 5)); // Check last write is terminated */
+}
+
void rtc_init() {
#ifdef ENABLE_RTC