diff --git a/examples/buffers/Makefile b/examples/buffers/Makefile new file mode 100644 index 0000000..36b3f40 --- /dev/null +++ b/examples/buffers/Makefile @@ -0,0 +1,10 @@ +FX2LIBDIR=../.. +BASENAME = buffers +SOURCES=buffers.c +DSCR_AREA= +INT2JT= +include $(FX2LIBDIR)/lib/fx2.mk +fx2_download: + ../download.sh build/$(BASENAME).ihx + + diff --git a/examples/buffers/buffers.c b/examples/buffers/buffers.c new file mode 100644 index 0000000..89b8b8a --- /dev/null +++ b/examples/buffers/buffers.c @@ -0,0 +1,141 @@ +/** + * Copyright (C) 2009 Ubixum, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + **/ + +#include + +#include +#include +#include +#include + +#define SYNCDELAY SYNCDELAY4 + +CREATE_BUFFER_AUTOPTR_SINGLE(buffer0,10) +CREATE_BUFFER_AUTOPTR_SINGLE(buffer1,10) +CREATE_BUFFER_AUTOPTR_SINGLE(buffer2,5) +__xdata BYTE data_buffer[10]; +void uart0_tx(char data); +void main(void) +{ + buffer0_init(); + buffer1_init(); + buffer2_init(); + SETCPUFREQ(CLK_48M); + // loop endlessly + for(;;) { + buffer0_push(0x45); + buffer0_push(0x46); + buffer0_push(0x47); + buffer0_push(0x48); + buffer2_push(0x21); + buffer1_push(0x35); + buffer1_push(0x36); + buffer1_push(0x37); + buffer1_push(0x38); + buffer1_push(0x39); + buffer1_push(0x40); + printf("Popping data\r\n"); + printf("Buffer 0 %02x\r\n",buffer0_pop()); + printf("Buffer 0 %02x\r\n",buffer0_pop()); + printf("Buffer 0 %02x\r\n",buffer0_pop()); + printf("Buffer 0 %02x\r\n",buffer0_pop()); + printf("Buffer 1 %02x\r\n",buffer1_pop()); + printf("Buffer 1 %02x\r\n",buffer1_pop()); + printf("Buffer 1 %02x\r\n",buffer1_pop()); + printf("Buffer 1 %02x\r\n",buffer1_pop()); + printf("Buffer 1 %02x\r\n",buffer1_pop()); + printf("Buffer 1 %02x\r\n",buffer1_pop()); + printf("Buffer 2 %02x\r\n",buffer2_pop()); + } +} + +void uart0_tx(char c) +{ + //Done in ASM to improve performance. It takes only 6 + //cycles to move the data out, however a delay has been + //introduced in order to get a baud rate of 115200 + //The mask which is to be written into the pin + OEA |= 0x04; + //An efficient UART bitbang routine in assembly + __asm + //Like #define in C. Can easily be used to change the pin + .equ _TX_PIN, _PA2 + //Disable interrupts + //This is used because timing is critical + //If the FX2 jumps into the ISR temporarily , it may cause transmit + //errors. By clearing EA, we can disable interrupts + clr _EA //(2 cycles) + //Move the data to be sent into the ACC + //The data which is to be shifted out is held in the dpl register + //We move the data into A for easy access to subsequent instructions + mov a , dpl //(2 cyles) + clr c //(1 cycle) + //We need to send out 8 bits of data + //Load r0 with value 8 + mov r0, #0x08 //(2 cycles) + //Create the start bit + clr _TX_PIN //(2 cycles) + //Precalculated delay since 1 cycle takes 88ns + //At 12Mhz, it should be about 83.33ns + //But it appears to be about 88ns + //These numbers have been verified using an analyzer + mov r1, #0x20 //(2 cycles) + 0006$: + //1 bit is about 8.6us + djnz r1, 0006$ //DJNZ on Rn takes (3 cycles) + //NOP takes about 1 cycle + //Add 2 more cycles of delay + //97 cycles + nop //(1 cycle) + nop //(1 cycle) + 0001$: + rrc a // (2 cycles). This rotates the accumulator right through the carry + //Move the carry into the port + mov _TX_PIN, c //(2 cycles) + //Now we need to add delay for the next + mov r1, #0x1F //(2 cycles) + //31*3 , 93 cycles of delay + 0004$: + djnz r1, 0004$ //(3 cycles) + nop //(1 cycle) + //3 more cycles of delay + //97 cycles + djnz r0, 0001$ //(3 cycles) + setb _TX_PIN //(2 cycles) This is for stop bit + //We need to delay the stop bit, otherwise we may get errors. + mov r1, #0x20 //(2 cycles) + 0005$: + djnz r1, 0005$ //(3 cycles) for DJNZ , Jump for 32*3 , 96 cycles + nop //(NOP takes 1 cycle) 97 cycles of delay + setb _EA; //Enable back the interrupts + __endasm; +} + +void putchar(char c) +{ +uart0_tx(c); +} + + + + + + + + + diff --git a/examples/download.sh b/examples/download.sh new file mode 100755 index 0000000..9f0d06b --- /dev/null +++ b/examples/download.sh @@ -0,0 +1,15 @@ +#!/bin/bash -e + +DEVS=$(lsusb|grep -E '(2a19|16c0|04b4|1d50|fb9a|1443)' |sed 's/:.*//;s/Bus //;s/Device //;s/ /\//') + +if [ -z "$1" ]; then + echo "$0: usage: $0 " + exit 1; +fi + +for dev in $DEVS;do + echo "Downloading $1 to $dev" + /sbin/fxload -D /dev/bus/usb/$dev -t fx2lp -I $1 +done + +exit 0 diff --git a/include/buffer/api.h b/include/buffer/api.h new file mode 100644 index 0000000..d8a9ffe --- /dev/null +++ b/include/buffer/api.h @@ -0,0 +1,106 @@ +/** \file include/buffer/api.h + * Used for defining a common API for accessing buffers on the FX2. + **/ + +#ifndef BUFFER_API_H +#define BUFFER_API_H +#include "fx2types.h" + +/** + * \brief Initializes a buffer. + **/ +BOOL bufferX_init(); + +/** + * \brief Gets the next byte from the UART buffer if the buffer is not empty. +**/ +BYTE bufferX_pop(); + +/** + * \brief Inserts a byte into the buffer if not full. + * Returns if the byte was inserted or not. + * TRUE - The data has been inserted into the buffer. + * FALSE - Buffer is full. Byte has not been inserted. +**/ +BOOL bufferX_push(BYTE data); + +/** + * \brief Returns if the buffer is full or not. + * TRUE - Buffer is full. + * FALSE - Buffer is not full. +**/ +BOOL bufferX_is_full(); + +/** + * \brief Returns if the buffer is empty or not. + * TRUE - Buffer is empty. + * FALSE - Buffer is not empty. +**/ +BOOL bufferX_is_empty(); + +/** + * \brief Returns the number of bytes which can be inserted into the buffer. +**/ +BYTE bufferX_bytes_left(); + +/** + * \brief Removes all the elements in the buffer. Flushes the entire buffer. +**/ +BYTE bufferX_flush(); + +/** + * \brief Returns the maximum size of the buffer. WARNING:(This is always less than 256 bytes). +**/ +BYTE bufferX_max_size(); + +/** + * \brief This function directly inserts the data into the current address of the buffer. + * WARNING: This function will overwrite the data in the current address location. + * \param BYTE data The data to be inserted into the buffer. + * Returns if the data has been added in the buffer or not. + * TRUE - Data has been added. + * FALSE - An error occured. The data has not been added to the buffer. +**/ +BOOL bufferX_insert_byte(BYTE data); + +/** + * \brief Returns the data at the current address pointed to, by the buffer without + * changing the address pointer. The data will still exist in the buffer. + * \param offset The number of locations the address pointer needs to be decremented in order + * to get access to the data. +**/ +BYTE bufferX_peek(BYTE offset); + +/** + * \brief Increments the address which is being pointed to by the buffer. + * WARNING: This function will cause the address to be incremented by 1. + * This will cause you to skip over data if the current address holds data which + * you would like to access. + * Returns if the address has been incremented or not. + * TRUE - The address has been incremented. + * FALSE - An error occured. The address could not be incremented. +**/ +BOOL bufferX_inc(); + +/** + * \brief Decrements the address which is being pointed to by the buffer. + * WARNING: This function will cause the address to be decremented by 1. + * This will cause you to skip over data if the current address holds data which + * you would like to access.(This function is equivalent to a pop without returning + * the data which has been removed). + * Returns if the address has been decremented or not. + * TRUE - The address has been decremented. + * FALSE - An error occured. The address could not be decremented. +**/ +BOOL bufferX_dec(); + +/** + * \brief Copies the source bytes into the destination bytes. + * \param src The source address location. + * \param dst The destination address into which the data has been copied. + * \param size The number of bytes which need to be copied from the source address + * into the destination address. +**/ +BYTE bufferX_copy_bytes(__xdata BYTE *src,__xdata BYTE *dst,BYTE size); + +#endif diff --git a/include/buffer/buffer.h b/include/buffer/buffer.h new file mode 100644 index 0000000..8e2b307 --- /dev/null +++ b/include/buffer/buffer.h @@ -0,0 +1,200 @@ +/** \file include/buffer/buffer.h + * Used for implementing the common API for accessing buffers on the FX2. + **/ +#ifndef BUFFER_BUFFER_H +#define BUFFER_BUFFER_H +#include "fx2types.h" +#include +#include + +/** + * \brief Stores the buffer number. This is incremented everytime the CREATE_BUFFER + * macro is called. WARNING: Maximum number of buffers supported is 256. + **/ +BYTE buffer_number; + +/** + * \brief Stores the current buffer number. Used to identify the buffer into which data was last inserted. + **/ +BYTE current_buffer_push; + +/** + * \brief Stores the current buffer number. Used to identify the buffer into which data was last removed. + **/ +BYTE current_buffer_pop; + +/** + * \brief Stores the current data. The data in the DPL is often over written because of the DPTR functions. + **/ +BYTE store_data; + + + +__sfr __at 0x9a head_MSB; +__sfr __at 0x9b head_LSB; +__sfr __at 0x9d tail_MSB; +__sfr __at 0x9e tail_LSB; + + +/** + * \brief Creates a buffer. + * \li name##_head - This is a single byte which stores the location of the head pointer. + * \li name##_tail - This is a single byte which stores the location of the tail pointer. + * \li name##_size - The size of the buffer. + * \li name##_buffer - The actual buffer. + **/ +#define CREATE_BUFFER(name, type, size) \ + volatile BYTE name##_head; \ + volatile __bit name##_head_inc; \ + volatile BYTE name##_tail; \ + type BYTE name##_buffer[1<