creole interface
This commit is contained in:
parent
8006853e6c
commit
cbdd0daaa6
2
creole
2
creole
|
@ -1 +1 @@
|
|||
Subproject commit 6d30be57f7c1853eb1fe26e91e0d0aae8811383b
|
||||
Subproject commit c18db4be57214903f2b1f6d5a7943eb40f644024
|
|
@ -1,59 +1,31 @@
|
|||
#include <zephyr/zephyr.h>
|
||||
#include <zephyr/sys/printk.h>
|
||||
#include <zephyr/net/socket.h>
|
||||
#include "buf.h"
|
||||
|
||||
bool
|
||||
buf_read_sock(int sock, struct bufptr *bp)
|
||||
{
|
||||
if (bp->left < 2)
|
||||
return false;
|
||||
|
||||
ssize_t l = zsock_recv(sock, bp->p, bp->left - 1, 0);
|
||||
if (l < 0)
|
||||
return false;
|
||||
|
||||
bp->left -= l;
|
||||
bp->p += l;
|
||||
*bp->p = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
buf_write_sock(int sock, struct bufptr *bp)
|
||||
{
|
||||
while (bp->left) {
|
||||
ssize_t l = zsock_send(sock, bp->p, bp->left, 0);
|
||||
if (l < 0)
|
||||
return false;
|
||||
bp->p += l;
|
||||
bp->left -= l;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
buf_writevf(struct bufptr *bp, const char *fmt, va_list va)
|
||||
{
|
||||
int w;
|
||||
|
||||
/* vsnprintk() returns the amount of bytes that would
|
||||
* be stored in the buffer if the buffer was big enough,
|
||||
* excluding the NUL terminator.
|
||||
* The function will _always_ write a NUL terminator
|
||||
* unless bp->left == 0.
|
||||
*/
|
||||
w = vsnprintk(bp->p, bp->left, fmt, va);
|
||||
int w = vsnprintk(bp->p, bp->left, fmt, va);
|
||||
|
||||
if (w < 0)
|
||||
return BUF_WRITE_ERR;
|
||||
|
||||
/* Return the number of bytes that are required to be
|
||||
* written.
|
||||
* Do not increment the buffer pointer, the truncated
|
||||
* data may not be safe.
|
||||
* Since w is the amount of required bytes minus the NUL
|
||||
* terminator, w == bp->left is still an out-of-memory
|
||||
* situation.
|
||||
*/
|
||||
if (w >= bp->left) {
|
||||
size_t oldleft = bp->left;
|
||||
buf->p += bp->left - 1;
|
||||
bp->left = 1;
|
||||
return w - oldleft + 1;
|
||||
return w - bp->left + 1;
|
||||
} else {
|
||||
bp->p += w;
|
||||
bp->left -= w;
|
||||
|
@ -64,10 +36,9 @@ buf_writevf(struct bufptr *bp, const char *fmt, va_list va)
|
|||
int
|
||||
buf_writef(struct bufptr *bp, const char *fmt, ...)
|
||||
{
|
||||
int r;
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
r = buf_writevf(bp, fmt, va);
|
||||
int r = buf_writevf(bp, fmt, va);
|
||||
va_end(va);
|
||||
return r;
|
||||
}
|
||||
|
|
|
@ -12,28 +12,10 @@ struct bufptr {
|
|||
|
||||
enum {
|
||||
BUF_OK = 0,
|
||||
BUF_WRITE_ERR = -1
|
||||
BUF_WRITE_ERR = -1,
|
||||
BUF_SOCK_ERR = -2
|
||||
};
|
||||
|
||||
/* Read from the socket into the buffer.
|
||||
* This function is meant to be called multiple times on the
|
||||
* same struct. The controller loads bp->left with the amount
|
||||
* of bytes it wishes to read, and continues until bp->left == 0.
|
||||
*
|
||||
* This function returns false if there was an error reading
|
||||
* from the socket.
|
||||
* A read of 0 bytes returns true.
|
||||
*/
|
||||
bool buf_read_sock(int sock, struct bufptr *bp);
|
||||
|
||||
/* Write from the bufptr into a socket.
|
||||
* This function is meant to be called once per prepared bufptr.
|
||||
*
|
||||
* This function returns false if there was an error on the
|
||||
* socket.
|
||||
*/
|
||||
bool buf_write_sock(int sock, struct bufptr *bp);
|
||||
|
||||
/* Write a formatted string to bp.
|
||||
* This function uses printf(), which means that it deals with
|
||||
* writing _C-strings_, not unterminated buffers.
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
#include <sys_clock.h>
|
||||
#include <sys/util.h>
|
||||
#include "control_loop_cmds.h"
|
||||
#include "creole.h"
|
||||
#include "creole_upsilon.h"
|
||||
#include "pin_io.h"
|
||||
#include "creole.h"
|
||||
|
||||
static inline uint32_t
|
||||
sign_extend(uint32_t in, unsigned len)
|
||||
|
@ -67,7 +69,7 @@ creole_word
|
|||
upsilon_usec(creole_word usec)
|
||||
{
|
||||
k_sleep(K_USEC(usec));
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
creole_word
|
||||
|
@ -82,7 +84,7 @@ upsilon_control_loop_read(creole_word *high_reg,
|
|||
*low_reg = cl_word_out[1];
|
||||
*cl_start_cmd = 0;
|
||||
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
creole_word
|
||||
|
@ -97,32 +99,85 @@ upsilon_control_loop_write(creole_word high_val,
|
|||
while (!*cl_finish_cmd);
|
||||
*cl_start_cmd = 0;
|
||||
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static size_t
|
||||
load_into_array(const struct creole_reader *start, creole_word *buf, size_t buflen)
|
||||
{
|
||||
size_t i = 0;
|
||||
struct creole_word w;
|
||||
struct creole_reader r = start;
|
||||
|
||||
while (creole_decode(&r, &w) && i < buflen) {
|
||||
buf[i++] = w.word;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
#define MAX_WL_SIZE 4096
|
||||
creole_word
|
||||
upsilon_load_waveform(struct creole_env *env, creole_word slot,
|
||||
creole_word db)
|
||||
{
|
||||
/* TODO */
|
||||
return 0;
|
||||
creole_word buf[MAX_WL_SIZE];
|
||||
size_t len = load_into_array(env->dats[db], buf, ARRAY_SIZE(buf));
|
||||
|
||||
if (len != MAX_WL_SIZE)
|
||||
return 0;
|
||||
|
||||
*wf_start_addr[slot] = &buf;
|
||||
*wf_refresh_start[slot] = 1;
|
||||
while (!*wf_refresh_finished[slot]);
|
||||
*wf_refresh_start[slot] = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
creole_word
|
||||
upsilon_exec_waveform(creole_word slot, creole_word dac)
|
||||
upsilon_arm_waveform(creole_word slot, creole_word hof, creole_word wait)
|
||||
{
|
||||
/* TODO */
|
||||
return 0;
|
||||
*wf_halt_on_finished[slot] = hof;
|
||||
*wf_time_to_wait[slot] = wait;
|
||||
*wf_arm[slot] = 1;
|
||||
|
||||
if (wait) {
|
||||
while (!*wf_finished[slot]);
|
||||
*wf_arm[slot] = 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
creole_word
|
||||
upsilon_sendval(creole_word num)
|
||||
upsilon_disarm_waveform(creole_word slot)
|
||||
{
|
||||
/* TODO */
|
||||
return 0;
|
||||
*wf_arm[slot] = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
creole_word
|
||||
upsilon_sendval(struct creole_env *env, creole_word num)
|
||||
{
|
||||
char buf[32];
|
||||
struct bufptr bp = {buf, sizeof(buf)};
|
||||
|
||||
return sock_printf(env->fd, &bp, "%u", num) == BUF_OK;
|
||||
}
|
||||
|
||||
creole_word
|
||||
upsilon_senddat(struct creole_env *env, creole_word db)
|
||||
{
|
||||
/* TODO */
|
||||
return 0;
|
||||
char buf[128];
|
||||
struct bufptr bp = {buf, 0};
|
||||
struct creole_word w;
|
||||
struct creole_reader r = start;
|
||||
|
||||
while (creole_decode(&r, &w) && bp.left < buflen) {
|
||||
if (w.word > 0xFF)
|
||||
return 0;
|
||||
buf[bp.left++] = w.word;
|
||||
}
|
||||
|
||||
return sock_write_buf(env->fd, &bp);
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include "sock.h"
|
||||
#include "buf.h"
|
||||
|
||||
LOG_MODULE_REGISTER(sock);
|
||||
|
||||
|
@ -47,6 +48,9 @@ server_accept_client(int server)
|
|||
struct sockaddr_in addr;
|
||||
socklen_t len = sizeof(addr);
|
||||
|
||||
/* Accept clients in a loop. This is halting so other threads will
|
||||
* be able to process clients.
|
||||
*/
|
||||
do {
|
||||
client = zsock_accept(server, (struct sockaddr *)&addr, &len);
|
||||
if (client < 0)
|
||||
|
@ -59,34 +63,71 @@ server_accept_client(int server)
|
|||
return client;
|
||||
}
|
||||
|
||||
int
|
||||
sock_vprintf(int sock, char *buf, int buflen, char *fmt, va_list va)
|
||||
bool
|
||||
sock_read_buf(int sock, struct bufptr *bp)
|
||||
{
|
||||
int w = vsnprintk(buf, buflen, fmt, va);
|
||||
if (w < 0)
|
||||
return b;
|
||||
else if (w <= buflen)
|
||||
return w - buflen;
|
||||
if (bp->left < 2)
|
||||
return false;
|
||||
|
||||
ssize_t left = w;
|
||||
char *p = buf;
|
||||
while (left > 0) {
|
||||
ssize_t i = zsock_send(sock, p, left, 0);
|
||||
if (i < 0)
|
||||
return 0;
|
||||
p += i;
|
||||
left -= i;
|
||||
ssize_t l = zsock_recv(sock, bp->p, bp->left - 1, 0);
|
||||
if (l < 0)
|
||||
return false;
|
||||
|
||||
bp->left -= l;
|
||||
bp->p += l;
|
||||
if (bp->left == 0) {
|
||||
LOG_ERR("internal out of bounds error in %s", __func__);
|
||||
k_fatal_halt(K_ERR_KERNEL_PANIC);
|
||||
}
|
||||
|
||||
return w;
|
||||
*bp->p = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
sock_write_buf(int sock, struct bufptr *bp)
|
||||
{
|
||||
/* Since send may not send all data in the buffer at once,
|
||||
* loop until it sends all data (or fails).
|
||||
*/
|
||||
while (bp->left) {
|
||||
ssize_t l = zsock_send(sock, bp->p, bp->left, 0);
|
||||
if (l < 0)
|
||||
return false;
|
||||
bp->p += l;
|
||||
bp->left -= l;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
sock_printf(int sock, char *buf, int buflen, char *fmt, ...)
|
||||
sock_vprintf(int sock, struct bufptr *bp, const char *fmt, va_list va)
|
||||
{
|
||||
int r = buf_writevf(bp, fmt, va);
|
||||
struct bufptr store_bp = *bp;
|
||||
if (r != BUF_OK)
|
||||
return r;
|
||||
|
||||
/* The difference between the initial and final values of
|
||||
* `left` is the amount of bytes written to the buffer.
|
||||
* Set left to this difference so that the only thing sent
|
||||
* is the bytes written by buf_writevf.
|
||||
*/
|
||||
store_bp.left -= bp->left;
|
||||
if (!sock_write_buf(sock, &store_bp)) {
|
||||
return BUF_SOCK_ERR;
|
||||
} else {
|
||||
return BUF_OK;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
sock_printf(int sock, struct bufptr *bp, const char *fmt, ...)
|
||||
{
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
int r = sock_vprintf(sock, buf, buflen, fmt, va);
|
||||
bool b = sock_vprintf(sock, bp, fmt, va);
|
||||
va_end(va);
|
||||
return r;
|
||||
return b;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,28 @@
|
|||
#pragma once
|
||||
#include <stdarg.h>
|
||||
#include "buf.h"
|
||||
|
||||
/* Initialize server to listen on the port passed as an argument. */
|
||||
/* Initialize server to listen on the port passed as an argument.
|
||||
*/
|
||||
int server_init_sock(int port);
|
||||
|
||||
/* Accept a client and allocate a file descriptor for the client. */
|
||||
/* Accept a client and allocate a file descriptor for the client.
|
||||
*/
|
||||
int server_accept_client(int server);
|
||||
|
||||
/* Read data into buffer. Returns false if error occurs. This is
|
||||
* raw binary (no NUL termination).
|
||||
*/
|
||||
bool sock_read_buf(int sock, struct bufptr *bp);
|
||||
|
||||
/* Write raw buffer data into socket. This data is raw binary and
|
||||
* does not have to be NUL terminated.
|
||||
*/
|
||||
bool sock_write_buf(int sock, struct bufptr *bp);
|
||||
|
||||
/* Write formatted string into socket. The user must provide a
|
||||
* buffer into which the formatted string is written. These return
|
||||
* with a buf.h error, or BUF_OK when successful.
|
||||
*/
|
||||
int sock_vprintf(int sock, struct bufptr *bp, const char *fmt, va_list va);
|
||||
int sock_printf(int sock, struct bufptr *bp, const char *fmt, ...);
|
||||
|
|
Loading…
Reference in New Issue