From: Robin Krens Date: Sun, 28 Jul 2019 20:00:58 +0000 (+0800) Subject: tm1637 signs of life, terminal builtin cmds X-Git-Url: https://robinkrens.nl/gitweb/?a=commitdiff_plain;h=094f4defd7ee3b672f9c690f57125893a64901c8;p=cortex-from-scratch tm1637 signs of life, terminal builtin cmds --- diff --git a/drivers/tm1637.c b/drivers/tm1637.c index a4e3842..517e0cf 100644 --- a/drivers/tm1637.c +++ b/drivers/tm1637.c @@ -5,8 +5,13 @@ * Initial version * * $DESCRIPTION$ - * Basic driver for the TM1637. The TM1637 is 7 segment - * ledclock peripheral. Communication is over I2C. + * Basic driver for the TM1637. The TM1637 is 8 segment + * ledclock peripheral. Communication is similar to I2C, + * but not completely. There is no address selecting. + * + * Alternative I2C protocol : (W)rite or (R)ead + * | Start | ADDRESS | W | ACK/NACK | DATA | ACK/NACK | (d+a*n) | St + * | Start | ADDRESS | R | ACK/NACK | DATA | ACK/NACK | (d+a*n) | St * * */ @@ -19,26 +24,154 @@ #include #include +#include #include +#define TIMEOUT 1000 + +#define DATASET 0x40 +#define CONTROL 0x80 +#define SETADDR 0xC0 + +#define DISPLAY_ON 0x8F +#define DISPLAY_OFF 0x11 + +/* STM32F1 microcontrollers do not provide the ability to pull-up SDA and SCL lines. Their +GPIOs must be configured as open-drain. So, you have to add two additional resistors to +pull-up I2C lines. Something between 4K and 10K is a proven value. +*/ void tm1637_init() { /* Program the peripheral input clock in I2C_CR2 Register in order to generate correct timings - Configure the clock control registers - Configure the rise time register + Configure the clock control registers CCR + Configure the rise time register TRIS Program the I2C_CR1 register to enable the peripheral - Set the START bit in the I2C_CR1 register to generate a Start condition ENABLE GPIOB6 and B7*/ - //regw_u8(RCC_APB1ENR, 0x1, 21, SETBIT); - //regw_u32(RCC_APB2ENR, 0x1, 3, SETBIT); + regw_u32(RCC_APB1ENR, 0x1, 21, SETBIT); + regw_u32(RCC_APB2ENR, 0x1, 3, SETBIT); // //regw_u8(AFIO_EVCR, 0x89, 0, SETBIT);// set event control register, output on ? - // regw_u32(GPIOB_CRL, 0xEE444444, 0, OWRITE); + regw_u32(GPIOB_CRL, 0xEE444444, 0, OWRITE); + + regw_u32(I2C_CR2, 0x2, 0, OWRITE); //2 MHz + regw_u8(I2C_TRISE, 0x3, 0, OWRITE); // MAX = 1000ns, TPCLK1 = 500ns (+1) + regw_u32(I2C_CCR, 0x000A, 0, OWRITE); // standard mode, output 100 kHz (100hz* / perip) + regw_u32(I2C_CR1, 0x1, 0, OWRITE); // enable + +} + +static void start_condition() { + + regw_u32(I2C_CR1, 0x1, 8, SETBIT); //start + +} + +static void stop_condition() { + + regw_u32(I2C_CR1, 0x1, 9, SETBIT); //stop +} + +int ack_recv() { + + int cnt = 0; + while(!(*I2C_SR1 & 0x1)) { + cnt++; + if (cnt > TIMEOUT) + return 0; + } + + return 1; + +} + +int delay() { + + int a = 0; + for (int i = 0; i < TIMEOUT; i++) + a++; +} + +void tm1637_start() { + +// regw_u32(I2C_CR1, 0x1, 8, SETBIT); +// uint32_t read_status = *I2C_SR1; + +// regw_u32(I2C_DR, DATASET, 0, OWRITE); + // conform DATA +// read_status = *I2C_SR1; +// read_status = *I2C_SR2; + + uint32_t statusr; + + start_condition(); + //uint32_t statusr = *I2C_SR1; // clear start_signal + regw_u32(I2C_DR, 0x40, 0, OWRITE); // write to address CMD + if(!ack_recv()) + cputs("TIMEOUT!"); + //statusr = *I2C_SR1; + //statusr = *I2C_SR2; + stop_condition(); + + //delay(); + + start_condition(); + //statusr = *I2C_SR1; // clear start_signal + regw_u32(I2C_DR, 0xC1, 0, OWRITE); + if(!ack_recv()) + cputs("TIMEOUT2!"); + //statusr = *I2C_SR1; + //statusr = *I2C_SR2; + regw_u32(I2C_DR, 0x7D, 0, OWRITE); + if(!ack_recv()) + cputs("TIMEOUT3!"); + stop_condition(); + + delay(); + + start_condition(); + statusr = *I2C_SR1; + regw_u32(I2C_DR, DISPLAY_ON, 0, OWRITE); + if(!ack_recv()) + cputs("TIMEOUT4!"); + stop_condition(); + + + /* regw_u32(I2C_CR1, 0x1, 8, SETBIT); //start + uint32_t read_status = *I2C_SR1; + regw_u32(I2C_DR, 0x40, 0, OWRITE); // write to address CMD + read_status = *I2C_SR1; + read_status = *I2C_SR2; + regw_u32(I2C_CR1, 0x1, 9, SETBIT); //stop + read_status = *I2C_SR1; + + regw_u32(I2C_CR1, 0x1, 8, SETBIT); //start + read_status = *I2C_SR1; + regw_u32(I2C_DR, 0xC1, 0, OWRITE); // segment address + read_status = *I2C_SR1; + read_status = *I2C_SR2; + regw_u32(I2C_DR, 0x7D, 0, OWRITE); // write a six + + regw_u32(I2C_CR1, 0x1, 9, SETBIT); //stop + read_status = *I2C_SR1; + + regw_u32(I2C_CR1, 0x1, 8, SETBIT); //start + read_status = *I2C_SR1; + + regw_u32(I2C_DR, DISPLAY_ON, 0, OWRITE); + read_status = *I2C_SR1; + regw_u32(I2C_CR1, 0x1, 9, SETBIT); //stop */ } +void tm1637_stop() { + + //regw_u32(I2C_CR1, 0x0, 9, SETBIT); +} + + + diff --git a/drivers/uart.c b/drivers/uart.c index a107548..4693c6f 100644 --- a/drivers/uart.c +++ b/drivers/uart.c @@ -75,7 +75,7 @@ static void wait() { for (int i = 0; i < 100; i++); } -extern void uart_putc(unsigned char ch) { +void uart_putc(unsigned char ch) { if (ch == '\n') { while (*USART1_SR & 0x0C) { } // transmit data register empty and complete @@ -102,10 +102,10 @@ char uart_getc(void) { // move to library -extern void uart_puts(unsigned char *str) { +/* extern void uart_puts(unsigned char *str) { int i; for (i = 0; i < strlen(str); i++) { uart_putc(str[i]); } -} +} */ diff --git a/include/drivers/tm1637.h b/include/drivers/tm1637.h index 319d5c5..4ad572a 100644 --- a/include/drivers/tm1637.h +++ b/include/drivers/tm1637.h @@ -2,5 +2,7 @@ #define __TM1637_H extern void tm1637_init(); +extern void tm1637_start(); +extern void tm1637_stop(); #endif diff --git a/include/lib/regfunc.h b/include/lib/regfunc.h index 6b0c50b..f194df0 100644 --- a/include/lib/regfunc.h +++ b/include/lib/regfunc.h @@ -1,4 +1,5 @@ /* regfunc.h */ extern char * regtohex(uint32_t ); +extern uint32_t hextoreg(char *); extern void regw_u8(volatile uint32_t *, uint8_t, short, short); extern void regw_u32(volatile uint32_t *, uint32_t, short, short); diff --git a/include/lib/string.h b/include/lib/string.h index e8e52f7..d19522b 100644 --- a/include/lib/string.h +++ b/include/lib/string.h @@ -3,3 +3,5 @@ extern void *memcpy(void*, void*, size_t); extern void *memset(void*, unsigned char, size_t); extern unsigned short *memsetw(unsigned short *dest, unsigned short val, size_t count); extern int strlen(const char *); +extern int strcmp(char *, char *); +extern char * strchr(const char *, char); diff --git a/include/sys/mmap.h b/include/sys/mmap.h index c3c91a1..4fd043d 100644 --- a/include/sys/mmap.h +++ b/include/sys/mmap.h @@ -68,6 +68,15 @@ #define AFIO_EVCR MEM_ADDR(0x40010000) +/* I2C REGISTER */ +#define I2C_CR1 MEM_ADDR(0x40005400) +#define I2C_CR2 MEM_ADDR(0x40005404) +#define I2C_DR MEM_ADDR(0x40005410) +#define I2C_SR1 MEM_ADDR(0x40005414) +#define I2C_SR2 MEM_ADDR(0x40005418) +#define I2C_CCR MEM_ADDR(0x4000541C) +#define I2C_TRISE MEM_ADDR(0x40005420) + /* EXTERNAL INTERRUPTS */ #define EXTI_IMR MEM_ADDR(0x40010400) #define EXTI_RTSR MEM_ADDR(0x40010408) diff --git a/lib/regfunc.c b/lib/regfunc.c index 6add220..b783901 100644 --- a/lib/regfunc.c +++ b/lib/regfunc.c @@ -40,8 +40,7 @@ void regw_u32(volatile uint32_t * reg, uint32_t val, short shift, short flag) { } /* Print out the hexidecimal representation of an integer - After implementation of a printf function, this code - will be obsolete. */ + After implementation of scanf or sth this will be obsolete. */ char hexbuf[8]; char * regtohex(uint32_t addr) { @@ -62,3 +61,28 @@ char * regtohex(uint32_t addr) { } return &hexbuf[0]; } +int singlehextoreg(char hex) { + + int conv = 0; + if (hex >= 'A' && hex <= 'F') + conv = hex - '7'; + + else { + conv = hex - '0'; + } + return conv; + +} + +uint32_t hextoreg(char * a) { + + uint32_t x = 0; + int tmp; + for(int i = 0; i < 8; i++) { + tmp = singlehextoreg(*a++); + x += tmp << (28 - (i * 4)); + } + return x; + +} + diff --git a/lib/string.c b/lib/string.c index b1618b0..2edc71a 100644 --- a/lib/string.c +++ b/lib/string.c @@ -36,3 +36,26 @@ int strlen(const char *str) for(retval = 0; *str != '\0'; str++) retval++; return retval; } + +int strcmp(char * a, char * b) { + + int alen = strlen(a); + int blen = strlen(b); + + if (alen != blen) + return 0; + + for (; alen != 0; alen--) { + if (*a++ != *b++) + return 0; + } + return 1; +} + +char * strchr(const char *s, char c) { + for (; *s; s++) + if (*s == c) + return (char *) s; + return 0; +} + diff --git a/main.c b/main.c index c5ee202..342059e 100644 --- a/main.c +++ b/main.c @@ -17,6 +17,9 @@ #include #include +#include +#include + #include #include #include @@ -24,19 +27,24 @@ void main() { ivt_init(); - uart_init(); +// cputs("ROBSYS LOADING...\n"); systick_init(); - led_init(); - sysinfo(); + tm1637_init(); + tm1637_start(); + + //uint32_t test = hextoreg("12345678"); + +// cputs(regtohex(test)); + //extern void stub(); //stub(); //__asm__ __volatile__ ("ldc p1, cr1, r0"); - while(1) { +/* while(1) { int r; for (int i = 0; i < 50000; i++) { r = 0; @@ -46,8 +54,8 @@ void main() r = 0; } led_off(); - } - // terminal(); + } */ + terminal(); for(;;) { diff --git a/sysinfo.c b/sysinfo.c index ba639a6..7f06334 100644 --- a/sysinfo.c +++ b/sysinfo.c @@ -22,7 +22,6 @@ uint32_t get_msp(void); void sysinfo() { uint32_t tmp = *MCU_ID; - cputs("# ROBSYS 0.1 LOADING...\n"); cputs("# DEVICE ID: "); if (tmp & 0x414) diff --git a/term.c b/term.c index 0628e1e..51eb9cf 100644 --- a/term.c +++ b/term.c @@ -6,10 +6,16 @@ #include #include +#include +#include + +#include #define SERIAL 1 #define BUFSIZE 200 - +#define MAXARGS 5 +#define WHITESPACE "\t\r\n " +#define BUILTINCMDS 3 int help(int, char**); @@ -26,27 +32,107 @@ static char buf[BUFSIZE]; struct cmd { char * name; - char * description; int (*function)(int argc, char ** argsv); }; -static struct cmd builtin[] = - { "info", "show info", help}; +struct cmd builtincmds[4]; int help(int argc, char ** argsv) { sysinfo(); return 0; } +int led(int argc, char ** argsv) { + + + if (argsv[1] != NULL) { + if (strcmp(argsv[1], "on")) { + cputs("LED ON\n"); + led_on(); + } + else if (strcmp(argsv[1], "off")) { + cputs("LED OFF\n"); + led_off(); + } + } + return 0; +} + +int show(int argc, char ** argsv) { + + if ((argsv[1] != NULL) && (strlen(argsv[1]) == 8)) { + + uint32_t * check = (uint32_t *) hextoreg(argsv[1]); + cputs("REGISTER 0x"); + cputs(argsv[1]); + cputs(" VALUE: "); + cputs(regtohex(*check)); + cputchar('\n'); + return 1; + + } + + return 0; +} + +int exec_cmd(char * buf) { + + int argc; + char *argv[MAXARGS]; + int i; + + // Parse the command buffer into whitespace-separated arguments + argc = 0; + argv[argc] = 0; + while (1) { + // gobble whitespace + while (*buf && strchr(WHITESPACE, *buf)) + *buf++ = 0; + if (*buf == 0) + break; + + // save and scan past next arg + if (argc == MAXARGS-1) { + cputs("Too many arguments"); + return 0; + } + argv[argc++] = buf; + while (*buf && !strchr(WHITESPACE, *buf)) + buf++; + } + argv[argc] = 0; + + // Lookup and invoke the command + if (argc == 0) + return 0; + for (i = 0; i < BUILTINCMDS; i++) { + if (strcmp(argv[0], builtincmds[i].name)) + return builtincmds[i].function(argc, argv); + } + cputs("Unknown command"); + return 0; + +} + void terminal() { - + + builtincmds[0].name = "help"; + builtincmds[0].function = help; + + builtincmds[1].name = "led"; + builtincmds[1].function = led; + + builtincmds[2].name = "show"; + builtincmds[2].function = show; + char *buf; - cputs("Terminal running!\n"); + cputs("WELCOME TO ROBSYS!\n"); while (1) { buf = readline("root# "); - /* if (buf != NULL) - if (runcmd(buf, tf) < 0) - break; */ + if (buf != NULL) + if (exec_cmd(buf) < 0) + break; } } +