|  | @@ -51,7 +51,7 @@ IRQHANDLER(esp,0)
 | 
	
		
			
				|  |  |  void esp_ota(const void *data, size_t len)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |      mask_irq(ESP_IRQ);
 | 
	
		
			
				|  |  | -    
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      ota.data = data;
 | 
	
		
			
				|  |  |      ota.len  = len;
 | 
	
		
			
				|  |  |      ESP_SPI_IRQ_SET = 1 << EL_UIRQ_OTA;
 | 
	
	
		
			
				|  | @@ -62,6 +62,103 @@ void esp_ota(const void *data, size_t len)
 | 
	
		
			
				|  |  |  	waitfor(ESP_IRQ);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +#define RINGBUF_BUF_SIZE 4096	/* Must be a power of 2 */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static __esplink uint8_t rb_buf[EL_RB_COUNT][2][RINGBUF_BUF_SIZE];
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static __esplink struct esplink_ringbuf_desc       rb_desc[EL_RB_COUNT];
 | 
	
		
			
				|  |  | +static volatile __esplink struct esplink_ptrs_dstr rb_dstr[EL_RB_COUNT];
 | 
	
		
			
				|  |  | +static volatile __esplink struct esplink_ptrs_ustr rb_ustr[EL_RB_COUNT];
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static void esplink_rb_init(void)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +    unsigned int i;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    for (i = 0; i < EL_RB_COUNT; i++) {
 | 
	
		
			
				|  |  | +	rb_desc[i].dstr.start = rb_buf[i][0];
 | 
	
		
			
				|  |  | +	rb_desc[i].dstr.size  = RINGBUF_BUF_SIZE;
 | 
	
		
			
				|  |  | +	rb_desc[i].ustr.start = rb_buf[i][1];
 | 
	
		
			
				|  |  | +	rb_desc[i].ustr.size  = RINGBUF_BUF_SIZE;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    esplink_head.rb.desc       = rb_desc;
 | 
	
		
			
				|  |  | +    esplink_head.rb.dstr       = (void *)rb_dstr;
 | 
	
		
			
				|  |  | +    esplink_head.rb.ustr       = (void *)rb_ustr;
 | 
	
		
			
				|  |  | +    esplink_head.rb.count      = EL_RB_COUNT;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/*
 | 
	
		
			
				|  |  | + * Read and write from ring buffers. These are atomic only; on failure
 | 
	
		
			
				|  |  | + * returns the amount of data/space available, but does NOT advance
 | 
	
		
			
				|  |  | + * any pointers nor copy any data.
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +size_t esp_rb_read(enum esplink_ringbuf_user ring, void *data, size_t len)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +    const size_t size          = rb_desc[ring].dstr.size;
 | 
	
		
			
				|  |  | +    const size_t sizemask      = size - 1;
 | 
	
		
			
				|  |  | +    const uint8_t * const base = rb_desc[ring].dstr.start;
 | 
	
		
			
				|  |  | +    size_t head                = rb_ustr[ring].head;
 | 
	
		
			
				|  |  | +    size_t tail                = rb_dstr[ring].tail;
 | 
	
		
			
				|  |  | +    size_t avail               = (head - tail) & sizemask;
 | 
	
		
			
				|  |  | +    uint8_t *p                 = data;
 | 
	
		
			
				|  |  | +    size_t xlen                = len;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (!len)
 | 
	
		
			
				|  |  | +	return 0;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (avail < xlen)
 | 
	
		
			
				|  |  | +	return avail;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (tail + xlen > size) {
 | 
	
		
			
				|  |  | +	size_t left = size - tail;
 | 
	
		
			
				|  |  | +	memcpy(p, base + tail, left);
 | 
	
		
			
				|  |  | +	p += left;
 | 
	
		
			
				|  |  | +	xlen -= left;
 | 
	
		
			
				|  |  | +	tail = 0;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    memcpy(p, base + tail, xlen);
 | 
	
		
			
				|  |  | +    tail = (tail + xlen) & sizemask;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    rb_dstr[ring].tail = tail;
 | 
	
		
			
				|  |  | +    ESP_SPI_IRQ_SET = 1 << EL_UIRQ_RINGBUF;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    return len;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +size_t esp_rb_write(enum esplink_ringbuf_user ring,
 | 
	
		
			
				|  |  | +		    const void *data, size_t len)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +    const size_t size          = rb_desc[ring].ustr.size;
 | 
	
		
			
				|  |  | +    const size_t sizemask      = size - 1;
 | 
	
		
			
				|  |  | +    uint8_t * const base       = rb_desc[ring].ustr.start;
 | 
	
		
			
				|  |  | +    size_t tail                = rb_ustr[ring].tail;
 | 
	
		
			
				|  |  | +    size_t head                = rb_dstr[ring].head;
 | 
	
		
			
				|  |  | +    size_t avail               = (tail - head - 1) & sizemask;
 | 
	
		
			
				|  |  | +    const uint8_t *p           = data;
 | 
	
		
			
				|  |  | +    size_t xlen                = len;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (!len)
 | 
	
		
			
				|  |  | +	return 0;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (avail < xlen)
 | 
	
		
			
				|  |  | +	return avail;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (head + xlen > size) {
 | 
	
		
			
				|  |  | +	size_t left = size - head;
 | 
	
		
			
				|  |  | +	memcpy(base + head, p, left);
 | 
	
		
			
				|  |  | +	p += left;
 | 
	
		
			
				|  |  | +	xlen -= left;
 | 
	
		
			
				|  |  | +	head = 0;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    memcpy(base + head, p, xlen);
 | 
	
		
			
				|  |  | +    head = (head + xlen) & sizemask;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    rb_dstr[ring].head = head;
 | 
	
		
			
				|  |  | +    ESP_SPI_IRQ_SET = 1 << EL_UIRQ_RINGBUF;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    return len;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  void esp_init(void)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |      static char __dram_data esp_signature[] = "Hej tomtebuggar slå i glasen!";
 | 
	
	
		
			
				|  | @@ -78,6 +175,8 @@ void esp_init(void)
 | 
	
		
			
				|  |  |      esplink_head.tsync         = &tsync;
 | 
	
		
			
				|  |  |      esplink_head.ota           = &ota;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    esplink_rb_init();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      esplink_head.magic         = ESPLINK_HEAD_MAGIC;
 | 
	
		
			
				|  |  |      ESP_SPI_IRQ                = (1 << EL_UIRQ_READY);
 | 
	
		
			
				|  |  |  
 |