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/zephyr.h>
|
||||||
#include <zephyr/sys/printk.h>
|
#include <zephyr/sys/printk.h>
|
||||||
#include <zephyr/net/socket.h>
|
|
||||||
#include "buf.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
|
int
|
||||||
buf_writevf(struct bufptr *bp, const char *fmt, va_list va)
|
buf_writevf(struct bufptr *bp, const char *fmt, va_list va)
|
||||||
{
|
{
|
||||||
int w;
|
|
||||||
|
|
||||||
/* vsnprintk() returns the amount of bytes that would
|
/* vsnprintk() returns the amount of bytes that would
|
||||||
* be stored in the buffer if the buffer was big enough,
|
* be stored in the buffer if the buffer was big enough,
|
||||||
* excluding the NUL terminator.
|
* excluding the NUL terminator.
|
||||||
* The function will _always_ write a NUL terminator
|
* The function will _always_ write a NUL terminator
|
||||||
* unless bp->left == 0.
|
* unless bp->left == 0.
|
||||||
*/
|
*/
|
||||||
w = vsnprintk(bp->p, bp->left, fmt, va);
|
int w = vsnprintk(bp->p, bp->left, fmt, va);
|
||||||
|
|
||||||
if (w < 0)
|
if (w < 0)
|
||||||
return BUF_WRITE_ERR;
|
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) {
|
if (w >= bp->left) {
|
||||||
size_t oldleft = bp->left;
|
return w - bp->left + 1;
|
||||||
buf->p += bp->left - 1;
|
|
||||||
bp->left = 1;
|
|
||||||
return w - oldleft + 1;
|
|
||||||
} else {
|
} else {
|
||||||
bp->p += w;
|
bp->p += w;
|
||||||
bp->left -= w;
|
bp->left -= w;
|
||||||
|
@ -64,10 +36,9 @@ buf_writevf(struct bufptr *bp, const char *fmt, va_list va)
|
||||||
int
|
int
|
||||||
buf_writef(struct bufptr *bp, const char *fmt, ...)
|
buf_writef(struct bufptr *bp, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
int r;
|
|
||||||
va_list va;
|
va_list va;
|
||||||
va_start(va, fmt);
|
va_start(va, fmt);
|
||||||
r = buf_writevf(bp, fmt, va);
|
int r = buf_writevf(bp, fmt, va);
|
||||||
va_end(va);
|
va_end(va);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,28 +12,10 @@ struct bufptr {
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
BUF_OK = 0,
|
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.
|
/* Write a formatted string to bp.
|
||||||
* This function uses printf(), which means that it deals with
|
* This function uses printf(), which means that it deals with
|
||||||
* writing _C-strings_, not unterminated buffers.
|
* writing _C-strings_, not unterminated buffers.
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
#include <sys_clock.h>
|
#include <sys_clock.h>
|
||||||
|
#include <sys/util.h>
|
||||||
#include "control_loop_cmds.h"
|
#include "control_loop_cmds.h"
|
||||||
#include "creole.h"
|
#include "creole.h"
|
||||||
#include "creole_upsilon.h"
|
#include "creole_upsilon.h"
|
||||||
#include "pin_io.h"
|
#include "pin_io.h"
|
||||||
|
#include "creole.h"
|
||||||
|
|
||||||
static inline uint32_t
|
static inline uint32_t
|
||||||
sign_extend(uint32_t in, unsigned len)
|
sign_extend(uint32_t in, unsigned len)
|
||||||
|
@ -67,7 +69,7 @@ creole_word
|
||||||
upsilon_usec(creole_word usec)
|
upsilon_usec(creole_word usec)
|
||||||
{
|
{
|
||||||
k_sleep(K_USEC(usec));
|
k_sleep(K_USEC(usec));
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
creole_word
|
creole_word
|
||||||
|
@ -82,7 +84,7 @@ upsilon_control_loop_read(creole_word *high_reg,
|
||||||
*low_reg = cl_word_out[1];
|
*low_reg = cl_word_out[1];
|
||||||
*cl_start_cmd = 0;
|
*cl_start_cmd = 0;
|
||||||
|
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
creole_word
|
creole_word
|
||||||
|
@ -97,32 +99,85 @@ upsilon_control_loop_write(creole_word high_val,
|
||||||
while (!*cl_finish_cmd);
|
while (!*cl_finish_cmd);
|
||||||
*cl_start_cmd = 0;
|
*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
|
creole_word
|
||||||
upsilon_load_waveform(struct creole_env *env, creole_word slot,
|
upsilon_load_waveform(struct creole_env *env, creole_word slot,
|
||||||
creole_word db)
|
creole_word db)
|
||||||
{
|
{
|
||||||
/* TODO */
|
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;
|
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
|
creole_word
|
||||||
upsilon_exec_waveform(creole_word slot, creole_word dac)
|
upsilon_arm_waveform(creole_word slot, creole_word hof, creole_word wait)
|
||||||
{
|
{
|
||||||
/* TODO */
|
*wf_halt_on_finished[slot] = hof;
|
||||||
return 0;
|
*wf_time_to_wait[slot] = wait;
|
||||||
|
*wf_arm[slot] = 1;
|
||||||
|
|
||||||
|
if (wait) {
|
||||||
|
while (!*wf_finished[slot]);
|
||||||
|
*wf_arm[slot] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
creole_word
|
creole_word
|
||||||
upsilon_sendval(creole_word num)
|
upsilon_disarm_waveform(creole_word slot)
|
||||||
{
|
{
|
||||||
/* TODO */
|
*wf_arm[slot] = 0;
|
||||||
return 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
|
creole_word
|
||||||
upsilon_senddat(struct creole_env *env, creole_word db)
|
upsilon_senddat(struct creole_env *env, creole_word db)
|
||||||
{
|
{
|
||||||
/* TODO */
|
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;
|
return 0;
|
||||||
|
buf[bp.left++] = w.word;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sock_write_buf(env->fd, &bp);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <zephyr/kernel.h>
|
#include <zephyr/kernel.h>
|
||||||
#include <zephyr/logging/log.h>
|
#include <zephyr/logging/log.h>
|
||||||
#include "sock.h"
|
#include "sock.h"
|
||||||
|
#include "buf.h"
|
||||||
|
|
||||||
LOG_MODULE_REGISTER(sock);
|
LOG_MODULE_REGISTER(sock);
|
||||||
|
|
||||||
|
@ -47,6 +48,9 @@ server_accept_client(int server)
|
||||||
struct sockaddr_in addr;
|
struct sockaddr_in addr;
|
||||||
socklen_t len = sizeof(addr);
|
socklen_t len = sizeof(addr);
|
||||||
|
|
||||||
|
/* Accept clients in a loop. This is halting so other threads will
|
||||||
|
* be able to process clients.
|
||||||
|
*/
|
||||||
do {
|
do {
|
||||||
client = zsock_accept(server, (struct sockaddr *)&addr, &len);
|
client = zsock_accept(server, (struct sockaddr *)&addr, &len);
|
||||||
if (client < 0)
|
if (client < 0)
|
||||||
|
@ -59,34 +63,71 @@ server_accept_client(int server)
|
||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
bool
|
||||||
sock_vprintf(int sock, char *buf, int buflen, char *fmt, va_list va)
|
sock_read_buf(int sock, struct bufptr *bp)
|
||||||
{
|
{
|
||||||
int w = vsnprintk(buf, buflen, fmt, va);
|
if (bp->left < 2)
|
||||||
if (w < 0)
|
return false;
|
||||||
return b;
|
|
||||||
else if (w <= buflen)
|
|
||||||
return w - buflen;
|
|
||||||
|
|
||||||
ssize_t left = w;
|
ssize_t l = zsock_recv(sock, bp->p, bp->left - 1, 0);
|
||||||
char *p = buf;
|
if (l < 0)
|
||||||
while (left > 0) {
|
return false;
|
||||||
ssize_t i = zsock_send(sock, p, left, 0);
|
|
||||||
if (i < 0)
|
bp->left -= l;
|
||||||
return 0;
|
bp->p += l;
|
||||||
p += i;
|
if (bp->left == 0) {
|
||||||
left -= i;
|
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
|
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_list va;
|
||||||
va_start(va, fmt);
|
va_start(va, fmt);
|
||||||
int r = sock_vprintf(sock, buf, buflen, fmt, va);
|
bool b = sock_vprintf(sock, bp, fmt, va);
|
||||||
va_end(va);
|
va_end(va);
|
||||||
return r;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,28 @@
|
||||||
#pragma once
|
#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);
|
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);
|
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