aboutsummaryrefslogtreecommitdiffstats
path: root/src/avr/usbserial.c
blob: 6dbe4f0db2ca4fce3a2f23a8d1184b980ae340cd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// Wrappers for AVR usb serial.
//
// Copyright (C) 2016,2017  Kevin O'Connor <kevin@koconnor.net>
//
// This file may be distributed under the terms of the GNU GPLv3 license.

#include <string.h> // memmove
#include "../lib/pjrc_usb_serial/usb_serial.h"
#include "board/misc.h" // console_sendf
#include "command.h" // command_dispatch
#include "sched.h" // DECL_INIT

static uint8_t receive_buf[MESSAGE_MAX], receive_pos;

void
usbserial_init(void)
{
    usb_init();
}
DECL_INIT(usbserial_init);

// Check for new incoming data
static void
console_check_input(void)
{
    for (;;) {
        if (receive_pos >= sizeof(receive_buf))
            break;
        int16_t ret = usb_serial_getchar();
        if (ret == -1)
            break;
        receive_buf[receive_pos++] = ret;
    }
}

// Remove from the receive buffer the given number of bytes
static void
console_pop_input(uint8_t len)
{
    uint8_t needcopy = receive_pos - len;
    if (needcopy) {
        memmove(receive_buf, &receive_buf[len], needcopy);
        sched_wake_tasks();
    }
    receive_pos = needcopy;
}

// Process any incoming commands
void
console_task(void)
{
    console_check_input();
    uint_fast8_t pop_count;
    int8_t ret = command_find_block(receive_buf, receive_pos, &pop_count);
    if (ret > 0)
        command_dispatch(receive_buf, pop_count);
    if (ret)
        console_pop_input(pop_count);
}
DECL_TASK(console_task);

// Encode and transmit a "response" message
void
console_sendf(const struct command_encoder *ce, va_list args)
{
    // Generate message
    static uint8_t buf[MESSAGE_MAX];
    uint8_t msglen = command_encodef(buf, ce, args);
    command_add_frame(buf, msglen);

    // Transmit message
    usb_serial_write((void*)buf, msglen);
    usb_serial_flush_output();
}