Created
May 11, 2012 22:11
-
-
Save kevinmehall/2662715 to your computer and use it in GitHub Desktop.
FIFO ring buffer for USB packets on xmega
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Bufferred BULK streaming | |
// http://nonolithlabs.com | |
// (C) 2011 Kevin Mehall (Nonolith Labs) <[email protected]> | |
// | |
// Licensed under the terms of the GNU GPLv3+ | |
#include "packetbuffer.h" | |
// CEE to PC buffer | |
Ringbuf in_ring; | |
unsigned char in_buf[PACKETS_BUFFER][IN_PACKET_SIZE]; | |
// PC to CEE buffers | |
Ringbuf out_a_ring; | |
unsigned char out_a_buf[PACKETS_BUFFER][OUT_PACKET_SIZE]; | |
Ringbuf out_b_ring; | |
unsigned char out_b_buf[PACKETS_BUFFER][OUT_PACKET_SIZE]; | |
void packetbuf_endpoint_init(void){ | |
USB_ep_in_init(1, USB_EP_TYPE_BULK_gc, IN_PACKET_SIZE); | |
USB_ep_out_init(2, USB_EP_TYPE_BULK_gc, OUT_PACKET_SIZE); | |
packetbuf_reset(); | |
} | |
void packetbuf_reset(void){ | |
ringbuf_reset(&in_ring); | |
ringbuf_reset(&out_a_ring); | |
ringbuf_reset(&out_b_ring); | |
USB_ep_in_reset(1); | |
USB_ep_out_reset(2); | |
USB_ep_out_reset(3); | |
ringbuf_usb_start_out(2, &out_a_ring, (uint8_t*) out_a_buf, OUT_PACKET_SIZE); | |
ringbuf_usb_start_out(3, &out_b_ring, (uint8_t*) out_b_buf, OUT_PACKET_SIZE); | |
} | |
void packetbuf_endpoint_poll(void){ | |
ringbuf_usb_poll_in(1, &in_ring, (uint8_t*) in_buf, IN_PACKET_SIZE); | |
ringbuf_usb_poll_out(2, &out_a_ring, (uint8_t*) out_a_buf, OUT_PACKET_SIZE); | |
ringbuf_usb_poll_out(3, &out_b_ring, (uint8_t*) out_b_buf, OUT_PACKET_SIZE); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Bufferred BULK streaming | |
// http://nonolithlabs.com | |
// (C) 2012 Kevin Mehall (Nonolith Labs) <[email protected]> | |
// (C) 2011 Ian Daniher (Nonolith Labs) <[email protected]> | |
// | |
// Licensed under the terms of the GNU GPLv3+ | |
#include <usb.h> | |
#define IN_PACKET_SIZE 64 | |
#define OUT_PACKET_SIZE 16 | |
#define PACKETS_BUFFER 16 | |
typedef struct ringbuf{ | |
// Index of the next readable position of the buffer | |
uint8_t start; | |
// Index of the next or pending writable position of the buffer | |
uint8_t end; | |
// Number of valid buffer slots | |
uint8_t count; | |
} Ringbuf; | |
/// Reset / initialize a ring buffer structure | |
inline static void ringbuf_reset(Ringbuf *r){ | |
r->start = r->end = r->count = 0; | |
} | |
inline static bool ringbuf_can_read(Ringbuf *r){return r->count>0;} | |
inline static bool ringbuf_can_write(Ringbuf *r){return r->count < PACKETS_BUFFER-1;} | |
inline static void ringbuf_after_take(Ringbuf *r){ | |
r->count--; | |
r->start = (r->start+1)%PACKETS_BUFFER; | |
} | |
inline static void ringbuf_after_put(Ringbuf *r){ | |
r->count++; | |
r->end = (r->end+1)%PACKETS_BUFFER; | |
} | |
inline static void ringbuf_usb_poll_in(uint8_t ep, Ringbuf *r, uint8_t* buf, uint8_t size){ | |
if (USB_ep_in_sent(ep) && ringbuf_can_read(r)){ | |
cli(); | |
USB_ep_in_start(ep, &buf[r->start*size], size); | |
ringbuf_after_take(r); | |
sei(); | |
} | |
} | |
inline static void ringbuf_usb_start_out(uint8_t ep, Ringbuf *r, uint8_t* buf, uint8_t size){ | |
USB_ep_out_start(ep, &buf[r->end*size]); | |
ringbuf_after_put(r); | |
} | |
inline static void ringbuf_usb_poll_out(uint8_t ep, Ringbuf *r, uint8_t* buf, uint8_t size){ | |
if (USB_ep_out_received(ep) && ringbuf_can_write(r)){ | |
cli(); | |
ringbuf_usb_start_out(ep, r, buf, size); | |
sei(); | |
} | |
} | |
// CEE to PC buffer | |
extern Ringbuf in_ring; | |
extern unsigned char in_buf[PACKETS_BUFFER][IN_PACKET_SIZE]; | |
// PC to CEE buffers | |
extern Ringbuf out_a_ring; | |
extern unsigned char out_a_buf[PACKETS_BUFFER][OUT_PACKET_SIZE]; | |
extern Ringbuf out_b_ring; | |
extern unsigned char out_b_buf[PACKETS_BUFFER][OUT_PACKET_SIZE]; | |
//determine if there is space in the slave-to-host ring buffer for another packet | |
inline static bool inbuf_can_write(void){return ringbuf_can_write(&in_ring);} | |
//determine if there are packets received from the host | |
inline static bool outbuf_a_can_read(void){return ringbuf_can_read(&out_a_ring);} | |
inline static bool outbuf_b_can_read(void){return ringbuf_can_read(&out_b_ring);} | |
inline static void outbuf_a_done_read(void){ringbuf_after_take(&out_a_ring);} | |
inline static void outbuf_b_done_read(void){ringbuf_after_take(&out_b_ring);} | |
inline static void inbuf_done_write(void){ringbuf_after_put(&in_ring);} | |
//returns location of buffer to fill | |
inline static uint8_t* inbuf_write_position(void){return in_buf[in_ring.end];} | |
inline static uint8_t* outbuf_a_read_position(void){return out_a_buf[out_a_ring.start];} | |
inline static uint8_t* outbuf_b_read_position(void){return out_b_buf[out_b_ring.start];} | |
void packetbuf_endpoint_init(void); | |
void packetbuf_reset(void); | |
void packetbuf_endpoint_poll(void); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment