summaryrefslogtreecommitdiff
path: root/pcr-controller/cmd_queue.c
blob: 6d1229658078bbb67c8813e258ae57b03082ba8a (plain) (blame)
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/*
 *  r3PCR Teensy Controller Code
 *
 *
 *  Copyright (C) 2013 Bernhard Tittelbach <xro@realraum.at>
 *
 *  This code is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  any later version.
 *
 *  This code is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with spreadspace avr utils. If not, see <http://www.gnu.org/licenses/>.
*/

#include <stdlib.h>
#include <stdio.h>
#include "cmd_queue.h"

//static assert:
//~ static int SDFLKJ[sizeof(int) == sizeof(int16_t)] = { 0 };

#define CMDQ_INPUT_LIST_LEN  2

typedef struct {
    uint8_t num_args;
    void* function_ptr;
    int16_t input_list[CMDQ_INPUT_LIST_LEN];
    uint8_t num_args_read;
} cmd_queue_item;

#define CMQ_QUEUE_LENGTH 4
cmd_queue_item cmd_queue_[CMQ_QUEUE_LENGTH];
uint8_t cmd_queue_todo_pos_ = 0;
uint8_t cmd_queue_fillargs_pos_ = 0;
uint8_t cmd_queue_next_here_ = 0;



#define CMDQ_READBUFFER_LEN  20
char cmdq_readbuffer_[CMDQ_READBUFFER_LEN];
uint8_t cmdq_readbuffer_pos_ = 0;

inline void cmdq_finishReadingArgument(void)
{
    cmdq_readbuffer_[cmdq_readbuffer_pos_] = '\0';
    cmdq_readbuffer_pos_ = 0;
    cmd_queue_[cmd_queue_fillargs_pos_].input_list[cmd_queue_[cmd_queue_fillargs_pos_].num_args_read++] = atoi(cmdq_readbuffer_);
}

//call regularily if in state CQ_READING
uint8_t cmdq_addCharToArgumentBuffer(uint8_t c)
{
    if ( cmd_queue_todo_pos_ == cmd_queue_next_here_ )
        return 1; //nothing to do with us, since no cmd's queued
    if (cmd_queue_[cmd_queue_fillargs_pos_].num_args_read >= CMDQ_INPUT_LIST_LEN)
        return 1;  //nothing to do with us
    if (cmd_queue_[cmd_queue_fillargs_pos_].num_args_read >= cmd_queue_[cmd_queue_fillargs_pos_].num_args )
        return 1;  //nothing to do with us
    //if input terminated by \n or \r then addArgument
    if (c == '\n' || c == '\r'  || c == ',' || c == 0x1B)
    {
        cmdq_finishReadingArgument();
        return 0;
    } else {    //continue reading
        cmdq_readbuffer_[cmdq_readbuffer_pos_++] = (char) c;
    }
    //if numlen +1 of readbuffer reached, addArgument as well (leave one char free to terminate with \0)
    if (cmdq_readbuffer_pos_ +1 >= CMDQ_READBUFFER_LEN)
    {
        cmdq_finishReadingArgument();
    }
    return 0;
}

void cmdq_queueCmdWithNumArgs(void* fptr, uint8_t num_args)
{
    if (num_args > CMDQ_INPUT_LIST_LEN)
    {
        printf("{\"cmd_ok\":false,\"error\":\"max args == %d\"}\r\n", CMDQ_INPUT_LIST_LEN);
        return; //can't do that Would hang cmdq
    }
    if ((cmd_queue_next_here_ +1) % CMQ_QUEUE_LENGTH == cmd_queue_todo_pos_) //for this check REQUIRED: CMQ_QUEUE_LENGTH > 2
        cmdq_doWork(); //no more space in queue -> execute now !
    cmd_queue_[cmd_queue_next_here_].num_args = num_args;
    cmd_queue_[cmd_queue_next_here_].function_ptr = fptr;
    cmd_queue_[cmd_queue_next_here_].num_args_read = 0;
    cmd_queue_fillargs_pos_ = cmd_queue_next_here_;
    cmd_queue_next_here_++;
    cmd_queue_next_here_ %= CMQ_QUEUE_LENGTH;
}

void cmdq_doWork(void)
{
    while ( cmd_queue_todo_pos_ != cmd_queue_next_here_ )
    {
        // is num_args_read_ now equal to num args we expect ?
        if (cmd_queue_[cmd_queue_todo_pos_].num_args_read != cmd_queue_[cmd_queue_todo_pos_].num_args )
            break;
        if (cmd_queue_[cmd_queue_todo_pos_].function_ptr == 0 )
            break;

        switch (cmd_queue_[cmd_queue_todo_pos_].num_args)
        {
            case 0:
                ((void(*)(void)) cmd_queue_[cmd_queue_todo_pos_].function_ptr)();
                break;
            case 1:
                ((void(*)(int16_t)) cmd_queue_[cmd_queue_todo_pos_].function_ptr)(cmd_queue_[cmd_queue_todo_pos_].input_list[0]);
                break;
            case 2:
                ((void(*)(int16_t,int16_t)) cmd_queue_[cmd_queue_todo_pos_].function_ptr)(cmd_queue_[cmd_queue_todo_pos_].input_list[0], cmd_queue_[cmd_queue_todo_pos_].input_list[1]);
                break;
        }
        cmd_queue_[cmd_queue_todo_pos_].num_args_read = 0;
        cmd_queue_[cmd_queue_todo_pos_].num_args = 0;
        cmd_queue_[cmd_queue_todo_pos_].function_ptr = 0;
        cmd_queue_todo_pos_++;
        cmd_queue_todo_pos_ %= CMQ_QUEUE_LENGTH;
        printf("{\"cmd_ok\":true}\r\n");
    }
}