User Tools

Site Tools


Differences

This shows you the differences between two versions of the page.

Link to this comparison view

c:tiny-shell-code [2018-02-12 10:16] (current)
Line 1: Line 1:
 +=====Tiny Shell sorce=====
 +
 +===main.c===
 +
 +<code C main.c>
 +/* $Id$ */
 +
 +#include <​ctype.h>​
 +#include <​stdint.h>​
 +#include <​stdlib.h>​
 +#include <​stdio.h>​
 +#include <​stddef.h>​
 +#include <​stdbool.h>​
 +#include <​string.h>​
 +#include <​unistd.h>​
 +
 +#include <​avr/​io.h>​
 +#include <​avr/​wdt.h>​
 +#include <​avr/​interrupt.h>​
 +#include <​avr/​pgmspace.h>​
 +#include <​util/​delay.h>​
 +
 +
 +#define BAUD 38400
 +#include <​util/​setbaud.h>​
 +
 +#include <​fifo.h>​
 +#include <​tools.h>​
 +#include <​shell.h>​
 +
 +
 +void uart_init(void) {
 +    /* UBRR - USART Baud Rate Register */
 +    UBRR0H = UBRRH_VALUE;​
 +    UBRR0L = UBRRL_VALUE;​
 +
 +    /* UCSR  - USART Control and Status Register */
 +    /* U2X - Double Speed Operation */
 +    UCSR0A &= ~(1 << U2X0);
 +
 +    /* UCSZ - USART Character Size, 8 bit */
 +    UCSR0B &= ~(1 << UCSZ02);
 +    UCSR0C |= (1 << UCSZ01) | (1 << UCSZ00);
 +
 +    /* USBS - USART Stop Bit Select */
 +    /* UPM - USART Parity Mode */
 +    UCSR0C &= ~(1 << USBS0) /* One Stop Bit */ &~(1 << UPM00) & ~(1 << UPM01); ​ /* No Parity */
 +
 +    UCSR0B |= (1 << TXEN0) | (1 << RXEN0); ​     /* Enable TX and RX */
 +    UCSR0B |= (1 << RXCIE0); ​   /* Enable Receive Interrupt */
 +    UCSR0B &= ~(1 << UDRIE0); ​  /* Disable Transmit Interrupt */
 +}
 +
 +void wdt_init(void) {
 +    wdt_enable(WDTO_30MS);​
 +    WDTCSR = (1 << WDIE);
 +}
 +
 +#define CLKD1    (1<<​CS20) ​                     /* CLK/8 */
 +#define CLKD8    (1<<​CS21) ​                     /* CLK/8 */
 +#define CLKD32 ​  ​(1<<​CS20) | (1<<​CS21) ​         /* CLK/32 */
 +#define CLKD64 ​  ​(1<<​CS22) ​                     /* CLK/64 */
 +#define CLKD128 ​ (1<<​CS20) | (1<<​CS22) ​         /* CLK/128 */
 +#define CLKD256 ​ (1<<​CS21) | (1<<​CS22) ​         /* CLK/256 */
 +#define CLKD1024 (1<<​CS20) | (1<<​CS21) | (1<<​CS22) ​     /* CLK/1024 */
 +
 +void timer_init(void) {
 +    TCCR2A = 0;
 +    TCCR2B = 0;
 +    TCCR2B = CLKD256;
 +    TIMSK2 |= (1 << TOIE2);
 +}
 +
 +void pwm0_init(void) {
 +    /* Timer 0 */
 +    TCCR0A = (1 << COM0A1) | (1 << COM0B1) | (1 << WGM00) | (1 << WGM01);
 +    TCCR0B = CLKD128;
 +    DDRD |= (1 << PORTD5) | (1 << PORTD6);
 +
 +    OCR0A = 10;                 /* #6 */
 +    OCR0B = 10;                 /* #5 */
 +}
 +
 +void pwm1_init(void) {
 +
 +    /* Timer 1 */
 +    TCCR1A = (1 << COM1A1) | (1 << COM1B1) | (1 << WGM10) | (1 << WGM11);
 +    TCCR1B = (1 << WGM12) | (1 << CS10) | (1 << CS12);
 +    DDRB |= (1 << PORTB1) | (1 << PORTB2);
 +
 +    OCR1A = 15;
 +    OCR1B = 15;
 +}
 +
 +
 +void pwm2_init(void) {
 +    /* Timer 2 */
 +    TCCR2A = (1 << COM2A1) | (1 << COM2B1) | (1 << WGM20) | (1 << WGM21);
 +    TCCR2B = (1 << CS20) | (1 << CS21) | (1 << CS22);
 +    DDRB |= (1 << PORTB3);
 +    DDRD |= (1 << PORTD3);
 +
 +    OCR2A = 10;
 +    OCR2B = 10;
 +}
 +
 +void adc_init() {
 +    ADMUX |= (1 << REFS0);
 +    ADCSRA = (1 << ADEN); ​                                 /* Enable ADC */
 +    ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); ​ /* Set base freq prescale */
 +}
 +
 +uint16_t adc_read(uint8_t ch) {
 +
 +    if (ch > 7)
 +        return 0;
 +
 +    ADMUX = (ADMUX & 0xF0) | ch;        /* Channel selection */
 +    ADCSRA |= (1 << ADSC); ​             /* Start conversion */
 +
 +    while (!ADCSRA & (1 << ADIF));
 +    ADCSRA |= (1 << ADIF);
 +
 +    return (ADC);
 +}
 +
 +
 +ISR(TIMER2_OVF_vect) {
 +/* Dummy code */
 +}
 +
 +ISR(USART_RX_vect) {
 +    volatile uint8_t c = UDR0;
 +
 +    if (c == '​\r'​) {
 +        fifo_putc(in,​ '​\n'​);​
 +        fifo_putc(out,​ '​\n'​);​
 +    }
 +
 +    fifo_putc(in,​ c);
 +    fifo_putc(out,​ c);
 +}
 +
 +ISR(WDT_vect) {
 +    wdt_reset();​
 +    volatile uint8_t c;
 +    while ((c = fifo_getc(out)) > 0) {
 +        while (!(UCSR0A & (1 << UDRE0)));
 +        UDR0 = c;
 +    }
 +    WDTCSR = (1 << WDIE);
 +}
 +
 +int16_t cmd_help(void) {
 +    outl("​Available commands:"​);​
 +    outl("​[s3|s5|s6] pos - set servo position"​);​
 +    outl("​help - this help"​);​
 +    return 1;
 +}
 +
 +
 +int16_t cmd_hello(void) {
 +    outl("​Hello!"​);​
 +    return 1;
 +}
 +
 +
 +
 +int16_t cmd_serv3(uint8_t * arg) {
 +    int8_t i = str2int(arg);​
 +    if (i >= 10 && i <= 37) {
 +        OCR2B = i;
 +        return i;
 +    } else {
 +        return -1;
 +    }
 +}
 +
 +int16_t cmd_serv5(uint8_t * arg) {
 +    int8_t i = str2int(arg);​
 +    if (i >= 10 && i <= 37) {
 +        OCR0B = i;
 +        return i;
 +    } else {
 +        return -1;
 +    }
 +}
 +
 +int16_t cmd_serv6(uint8_t * arg) {
 +    int8_t i = str2int(arg);​
 +    if (i >= 10 && i <= 37) {
 +        OCR2A = i;
 +        return i;
 +    } else {
 +        return -1;
 +    }
 +}
 +
 +
 +int16_t cmd_delay(uint8_t * arg) {
 +    int16_t n = str2int(arg),​ i = n;
 +    if (i < 0)
 +        i = -i;
 +    while (i > 0) {
 +        _delay_ms(100);​
 +        i--;
 +    }
 +    return n;
 +}
 +
 +cdef_t cdef[] = {
 +    {"​help",​ &​cmd_help,​ 0},
 +    {"​hello",​ &​cmd_hello,​ 0},
 +    {"​s3",​ &​cmd_serv3,​ 1},
 +    {"​s5",​ &​cmd_serv5,​ 1},
 +    {"​s6",​ &​cmd_serv6,​ 1},
 +    {"​delay",​ &​cmd_delay,​ 1} ,
 +    {"​sleep",​ &​cmd_delay,​ 1}
 +};
 +
 +#define STR_LEN 64
 +
 +uint8_t *prompt = "​READY>";​
 +
 +int main() {
 +    fifo_iohook();​
 +    uart_init();​
 +    wdt_init();
 +    timer_init();​
 +    pwm0_init();​
 +    pwm1_init();​
 +    pwm2_init();​
 +    adc_init();
 +    sei();
 +
 +    outl("​\r\nTINY SHELL V01");
 +    outs(prompt);​
 +
 +    uint8_t str[STR_LEN];​
 +    memset(str, 0, STR_LEN);
 +
 +    _delay_ms(1000);​
 +
 +    while (1) {
 +
 +        uint8_t *s;
 +        s = str;
 +        while (fifo_gett(in,​ str, STR_LEN, '​\r'​) > 0) {
 +
 +            shell(str, cdef, sizeof(cdef) / sizeof(cdef[0]));​
 +            outs("​\r\n"​);​
 +            outs(prompt);​
 +
 +        }
 +        _delay_ms(100);​
 +    }
 +}
 +</​code>​
 +
 +===fifo.c===
 +
 +<code C fifo.c>
 +/* $Id$ */
 +
 +#include <​stdint.h>​
 +#include <​stdbool.h>​
 +#include <​string.h>​
 +#include <​stdio.h>​
 +
 +
 +#include <​tools.h>​
 +#include <​fifo.h>​
 +
 +#ifndef FIFO_BUFFER_SIZE
 +#define FIFO_BUFFER_SIZE 128
 +#endif
 +
 +static uint8_t inbuf[FIFO_BUFFER_SIZE];​
 +static uint8_t outbuf[FIFO_BUFFER_SIZE];​
 +
 +FIFO fifo_in, fifo_out;
 +FIFO *in, *out;
 +
 +void outc(uint8_t c) {
 +    fifo_putc(out,​ c);
 +}
 +
 +void outs(uint8_t * str) {
 +    fifo_puts(out,​ str);
 +}
 +
 +void outl(uint8_t * str) {
 +    fifo_puts(out,​ str);
 +    fifo_puts(out,​ "​\r\n"​);​
 +}
 +
 +
 +int uart_putchar(char c, FILE * stream) {
 +    return fifo_putc(&​fifo_out,​ c);
 +}
 +
 +int uart_getchar(FILE * stream) {
 +    return (int)fifo_getc(&​fifo_out);​
 +}
 +
 +FILE uart_str = FDEV_SETUP_STREAM(uart_putchar,​ uart_getchar,​ _FDEV_SETUP_RW);​
 +
 +void fifo_iohook(void) {
 +    in = &​fifo_in;​
 +    out = &​fifo_out;​
 +
 +    fifo_init(in,​ inbuf, sizeof(inbuf));​
 +    fifo_init(out,​ outbuf, sizeof(outbuf));​
 +
 +    stdout = stdin = stderr = &​uart_str;​
 +}
 +
 +void fifo_init(FIFO * b, uint8_t * buffer, uint8_t buffer_len) {
 +    if (b && buffer) {
 +        memset((void **)buffer, 0, buffer_len);​
 +        b->​buffer_len = buffer_len;
 +        b->​buffer = buffer;
 +        b->head = 0;
 +        b->tail = 0;
 +    }
 +}
 +
 +uint8_t fifo_count(const FIFO * b) {
 +    if (b) {
 +        return (b->head - b->​tail);​
 +    }
 +    return 0;
 +}
 +
 +static bool fifo_full(const FIFO * b) {
 +    if (b) {
 +        return (fifo_count(b) == b->​buffer_len);​
 +    }
 +    return true;
 +}
 +
 +bool fifo_empty(const FIFO * b) {
 +    if (b) {
 +        return (fifo_count(b) == 0);
 +    }
 +    return true;
 +}
 +
 +uint8_t fifo_peek(const FIFO * b) {
 +    uint8_t data = 0;
 +
 +    if (!fifo_empty(b)) {
 +        data = b->​buffer[b->​tail % b->​buffer_len];​
 +    }
 +    return data;
 +}
 +
 +bool fifo_back(FIFO * b) {
 +    if (!fifo_empty(b)) {
 +        b->​head--;​
 +        return true;
 +    }
 +    return false;
 +}
 +
 +uint8_t fifo_getc(FIFO * b) {
 +    uint8_t data = 0;
 +
 +    if (!fifo_empty(b)) {
 +        data = b->​buffer[b->​tail % b->​buffer_len];​
 +        b->​tail++;​
 +    }
 +    return data;
 +}
 +
 +bool fifo_putc(FIFO * b, uint8_t data) {
 +    bool status = false;
 +
 +    if (b) {
 +        if (!fifo_full(b)) {
 +            b->​buffer[b->​head % b->​buffer_len] = data;
 +            b->​head++;​
 +            status = true;
 +        }
 +    }
 +    return status;
 +}
 +
 +uint8_t fifo_puts(FIFO * b, uint8_t * string) {
 +    if (b) {
 +        for (uint8_t i = 0; i < str_len(string);​ i++) {
 +            if (!fifo_putc(b,​ string[i]))
 +                return i;
 +        }
 +    }
 +}
 +
 +bool fifo_scanc(FIFO * b, uint8_t c) {
 +    if (b) {
 +        if (!fifo_empty(b)) {
 +            uint8_t tail = b->tail;
 +
 +            for (uint8_t i = 0; i < fifo_count(b);​ i++) {
 +                uint8_t data = b->​buffer[tail % b->​buffer_len];​
 +
 +                if (data == c) {
 +                    return true;
 +                }
 +                tail++;
 +            }
 +        }
 +        return false;
 +    }
 +}
 +
 +uint8_t fifo_gett(FIFO * b, uint8_t * str, uint8_t len, uint8_t term) {
 +    if (b) {
 +        memset((void *)str, 0, len);
 +
 +        if (fifo_scanc(b,​ term) && str) {
 +            uint8_t i = 0, c = 0;
 +
 +            while ((c = fifo_getc(b)) != 0 && c != term && i < len) {
 +                str[i] = c;
 +                i++;
 +            }
 +            return i;
 +        }
 +        return 0;
 +    }
 +}
 +
 +/* EOF */
 +</​code>​
 +
 +===fifo.h===
 +
 +<code C fifo.h>
 +/* $Id$ */
 +
 +#ifndef UART_H_IUI
 +#define UART_H_IUI
 +
 +#define FIFO_BUFFER_SIZE 128
 +//extern static uint8_t inbuf[FIFO_BUFFER_SIZE];​
 +//extern static uint8_t outbuf[FIFO_BUFFER_SIZE];​
 +
 +typedef struct fifo {
 +    volatile unsigned head;
 +    volatile unsigned tail;
 +    volatile uint8_t *buffer;
 +    unsigned buffer_len;
 +} FIFO;
 +
 +extern FIFO fifo_in, fifo_out;
 +extern FIFO *in, *out;
 +
 +void fifo_iohook(void);​
 +
 +void fifo_init(FIFO * b, uint8_t * buffer, uint8_t buffer_len);​
 +uint8_t fifo_count(const FIFO * b);
 +static bool fifo_full(const FIFO * b);
 +bool fifo_empty(const FIFO * b);
 +uint8_t fifo_peek(const FIFO * b);
 +uint8_t fifo_getc(FIFO * b);
 +bool fifo_putc(FIFO * b, uint8_t data);
 +uint8_t fifo_puts(FIFO * b, uint8_t * str);
 +bool fifo_scanc(FIFO * b, uint8_t c);
 +uint8_t fifo_gett(FIFO * b, uint8_t * str, uint8_t len, uint8_t);
 +
 +bool fifo_back(FIFO * b);
 +
 +void outc(uint8_t c);
 +void outs(uint8_t * str);
 +void outl(uint8_t * str);
 +
 +
 +#endif
 +/* EOF */
 +</​code>​
 +
 +
 +===tools.c===
 +
 +<code C tools.c>
 +/* $Id$ */
 +
 +#include <​stdint.h>​
 +#include <​stdbool.h>​
 +#include <​tools.h>​
 +
 +uint16_t str_len(uint8_t * str) {
 +    uint16_t i = 0;
 +    while (str[i] != 0)
 +        i++;
 +    return i;
 +}
 +
 +uint8_t *str_replc(uint8_t ** str, uint8_t c, uint8_t r) {
 +    uint16_t i = 0;
 +    while ((*str)[i] != 0) {
 +        if ((*str)[i] == c)
 +            (*str)[i] = r;
 +        i++;
 +    }
 +    return (*str);
 +}
 +
 +bool str_cmp(uint8_t * str1, uint8_t * str2) {
 +    uint8_t i = 0;
 +    while (str1[i] != 0 && str2[i] != 0) {
 +        if ((str1[i] != str2[i]) || (str1[i + 1] != str2[i + 1]))
 +            return false;
 +        i++;
 +    }
 +    return true;
 +}
 +
 +uint8_t *str_ltrim(uint8_t * str, uint8_t c) {
 +    while (str[0] == c && str[0] != 0)
 +        str++;
 +    return str;
 +}
 +
 +uint8_t *str_trim(uint8_t * str, uint8_t c) {
 +    while (str[0] == c && str[0] != 0)
 +        str++;
 +
 +    uint8_t i = str_len(str) - 1;
 +    while (str[i] == c && i > 0) {
 +        i--;
 +    }
 +    str[++i] = 0;
 +    return str;
 +}
 +
 +int32_t int_pow(uint8_t n, uint8_t s) {
 +    int64_t i = 1;
 +    while (s--) {
 +        i = i * n;
 +    }
 +    return i;
 +}
 +
 +int32_t str2int(uint8_t * str) {
 +    uint8_t l = str_len(str);​
 +    uint8_t i = l;
 +    int16_t n = 0;
 +    while (i > 0) {
 +        if (str[i - 1] <= '​9'​ && str[i - 1] >= '​0'​)
 +            n += (str[i - 1] - '​0'​) * int_pow(10, l - i);
 +        i--;
 +    }
 +    if (str[0] == '​-'​)
 +        n = -n;
 +    return n;
 +}
 +
 +uint8_t int2str(int32_t num, uint8_t * str, uint8_t buf_len, int16_t base) {
 +    static char digits[] = "​0123456789abcdefghijklmnopqrstuvwxyz";​
 +    uint8_t i = 0, sign = 0;
 +    if (num < 0) {
 +        sign = '​-';​
 +        num = -num;
 +    }
 +    do {
 +        str[i++] = digits[num % base];
 +    } while ((num /= base) > 0 && i < buf_len);
 +
 +    if (sign)
 +        str[i++] = '​-';​
 +    str[i] = 0;
 +
 +    uint8_t len = i - 1;
 +    uint8_t c, b = 0;
 +
 +    while (i-- && b < i) {
 +        c = str[b];
 +        str[b] = str[i];
 +        str[i] = c;
 +        b++;
 +    }
 +    return len;
 +}
 +
 +uint8_t *tok_comp(uint8_t ** str, uint8_t c, uint8_t * end) {
 +    uint8_t *p = *str;
 +    if (p >= end)
 +        return 0;
 +    if (p[0] == 0)
 +        return 0;
 +
 +    uint8_t i = 0;
 +
 +    while (i < str_len(p)) {
 +        if (p[i] == c || p[i] == 0)
 +            break;
 +        i++;
 +    }
 +    p[i] = 0;
 +
 +    (*str) += ++i;
 +    i = 0;
 +
 +    while ((*str)[i] == c)
 +        (*str)++;
 +    return p;
 +}
 +
 +/* EOF */
 +</​code>​
 +===tools.h===
 +
 +<code C tools.h>
 +/* $Id$ */
 +
 +#ifndef TOOLS_H_IRT
 +#define TOOLS_H_IRT
 +
 +#define MAX_LINE_LEN 1024
 +
 +uint16_t str_len(uint8_t * str);
 +bool str_cmp(uint8_t * str1, uint8_t * str2);
 +uint8_t *str_ltrim(uint8_t * str, uint8_t c);
 +uint8_t *str_trim(uint8_t * str, uint8_t c);
 +int32_t int_pow(uint8_t n, uint8_t s);
 +int32_t str2int(uint8_t * str);
 +uint8_t int2str(int32_t num, uint8_t * str, uint8_t str_len, int16_t base);
 +uint8_t *str_endp(uint8_t * str);
 +uint8_t *tok_comp(uint8_t ** str, uint8_t c, uint8_t * end);
 +
 +#endif
 +/* EOF */
 +</​code>​