--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+unsubscribe@arduino.cc.
Hi Andrew,
I am one of those how asked again and again to enhance some buffer sizes and speed settings:
If I understand the compilation process of an ino-file correctly, all include files are "concatinated" and then compiled.
Then it shoud be possible to do the following:
Idea 3 (or is it your idea 1?):
For the serial buffer enclose the "SERIAL_BUFFER_SIZE" in RingBuffer.h in:
#ifndef SERIAL_BUFFER_SIZE
#define SERIAL_BUFFER_SIZE 64
#endif
For I2C-devices enclose the "BUFFER_LENGTH" in Wire.h in:
#ifndef BUFFER_LENGTH
#define BUFFER_LENGTH 32
#endif
-- You received this message because you are subscribed to the Google Groups "Developers" group. To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@arduino.cc.
-- You received this message because you are subscribed to the Google Groups "Developers" group. To unsubscribe from this group and stop receiving emails from it, send an email to developers+unsubscribe@arduino.cc.
-- You received this message because you are subscribed to the Google Groups "Developers" group. To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@arduino.cc.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@arduino.cc.
Personally there should be custom.h style defines for things like
SERIAL[1 | 2 | 3 | 4]_RX_DISABLE
SERIAL[1 | 2 | 3 | 4]_TX_DISABLE
SERIAL[1 | 2 | 3 | 4]_RX_BUFF_SIZE
SERIAL[1 | 2 | 3 | 4]_TX_BUFF_SIZE
I2Cn_DISABLE
I2Cn_BUFF_SIZE
SPIn_DISABLE
SPIn_BUFF_SIZE
SDCARD_BUFF_SIZE
ETHER_BUFF_SIZE
Then core part has
#if not defined SERIAL2_RX_DISABLE
#if not defined SERIAL2_RX_BUFF_SIZE
#define SERIAL2_RX_BUFF_SIZE <defualt>
#endif
uint8_t serial2_rx_buff[ SERIAL2_RX_BUFF_SIZE ];
Buffer Serial2_RX( serial2_rx_buff, SERIAL2_RX_BUFF_SIZE );
#endifBuffer class to have read and write handling with volatiles for ptrs or index in buffer for Read and Write but consist of
uint8_t *buff;
int size;
int RD_idx;
int WR_idx
uint8_t HW_over;
uint8_t SW_over;
HW_over being count of discarded bytes for Pairty, or Overrun errors
SW_over being discards becasue before was full
Reading of either status resets them to zero.
Once you have that THEN you can consider having variable buffer sizing.
I looked at it for Mega and Due and gave up as would take to long to restructure code properly as I would have preferred buffers for a Due first of
serial n RX TX
1 16 or 64 256
2 512 512
3 0 512
4 disabled
Persoanlly building a common buffer class would help more libraries for other modules, and reduce code size and associated handling issues, and would be a good first step
Hi Thomas,
thanks for your answer.
(1) The UART buffer size in the SAM3X8E is only one byte. The
Serial Buffer is managed by the library code not only on reading
the data from the chip as an ISR but also manages the data
transfer to the user buffer partially in an interrupt disabled
state properly. When I would use Serial.onReceive() I must
duplicate most of the code of the library but with a changed
buffer size. That is possible but not really a good.
(2) In my Arduino Due library code, I cannot find a call of
Wire::transfer(...). I use "WireDev.write(Data, DataSize);" and
"WireDev.requestFrom(..)". It may be that your call is available
for the 8 -bit CPUs. I read or write only one page at a time.
After this time, the CPU is clearly in interrupt enable state and
can handle other interrupts e.g. from the serial device or a power
fail interrupt. A power fail immediatly aborts my normal execution
flow handling the power fail. I big data transfer is not
appropriate, but the buffer must have a size of at least the page
size of the EEPROM.
Best Regards,
Dieter
-- You received this message because you are subscribed to the Google Groups "Developers" group. To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@arduino.cc.
Hi,
I asked the team to allow, that a user can change the default sizes from within the project.
But of cause, you are not and cannot be responsible for the bugs
a user implements. Don't try it.
Best Regards,
Dieter
-- You received this message because you are subscribed to the Google Groups "Developers" group. To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@arduino.cc.
Paul,that is correct. That's part of why I am not a big fan is the idea of exposing the compile time sizing of a ringbuffer that may or may not be present to begin with.- Thomas
--On Fri, Jan 13, 2017 at 1:00 PM, Paul Carpenter <paul@pcserviceselectronics.co.uk> wrote:If you are doing DMA then a standard ringbuffer is not your chosen
implementation, you are more likely to be using double buffering
(in software alone or hardware and software).
Considering how I have dealt with SMA, DUAL channel DMA, multiple DMA
buffers and other techniques since about 1979, on many systems and never was
a DMA to Ring Buffer ever considered.
Thomas Roell wrote:
Dieter,
I was not commenting on what was currently implemented, but what should be done to avoid those issues going forward. So none of the 2 APIs is implemented currently in the official Arduino source base (yes, they are implemented in the STM32L4 core, but that is not really relevant here).
The whole issue is a tad of a mess. A callback from the ISR level may have an impact on the responsiveness of the overall system. So a callback is best handled via the ARM Cortex PendSV mechanism. On the other hand it seems bad to expose the serial buffer size as a configurable option to the end user. Just because it would work for a simple ISR driver UART driver does not mean it would work for a FIFO/DMA based UART. So why drive towards a predictable incompatibility ?
N.b. that in POSIX you have setvbuf(). Perhaps something like that where the user can specify an additional RX/TX buffer over a builtin unspecified buffering scheme might be a better option.
- Thomas
--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+unsubscribe@arduino.cc.
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+unsubscribe@arduino.cc.
--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+unsubscribe@arduino.cc.
Paul,let's go back to the original problem. Somebody needed larger buffering capability to be able to absorbe longer latency between when UART data arrived and when it was processed by the code.As is right now, the public API of the HardwareSerial class does neither document nor require the use of a ringbuffer. There are enough examples where you simply will not have a resizeable ringbuffer (double-buffered DMA, or hardware FIFO).So that really leaves only 2 options:(1) Add a callback mechanism so that the existing API can be used to read data from whatever mechanism is used internally (that means the application needs to do the buffering)(2) Add a secondary mechanism to plug in a secondary ringbuffer (that may or may not replace the primary mechanism).However (2) is more or less the same as (1), but this time the code to deal with the additional buffer is in the HardwareSerial class and carried around for all applications, whether they use this mechanism or not.IMHO (1) is doable with a standard RingBuffer class and a simple callback. It would be odd to force the overhead of (2) for everybody else.- Thomas
One already exists as yet another ring buffer implementation in Due Core
set, probably in other ARM implementations maybe in x86 and other
architectures.
None have been used in serial as far as I can see. I looked at sorting it
briefly, but saw the core build issues amongst other things like NIH
Andrew Kroll wrote:
Ring buffer libraries exist... perhaps they should be leveraged.
On Fri, Jan 13, 2017 at 3:13 PM, Paul Carpenter <pa...@pcserviceselectronics.co.uk <mailto:paul@pcserviceselectronics.co.uk>> wrote:
It would make no difference to special DMA cases that need other
buffer handling class, and then may need a dual/multiple buffer handling
which even then may be a whole set of different sized buffers. May even
support ring buffer and DMA buffers to switch between commands and block
transfer modes.
A standard ring buffer class would support many cases that currently
support
ring buffers, then they can be changed by whatever means with peripheral
control to stem flow and stop race or other conditions. The best way
to be
able to change a buffer size is when the buffer is EXTERNAL to any
form of
a class where a fixed type buffer can only be instantiated at one fixed
size. Otherwise we start getting into vectors and the like.
Thomas Roell wrote:
Paul,
that is correct. That's part of why I am not a big fan is the
idea of exposing the compile time sizing of a ringbuffer that
may or may not be present to begin with.
- Thomas
On Fri, Jan 13, 2017 at 1:00 PM, Paul Carpenter
<pa...@pcserviceselectronics.co .uk
<mailto:paul@pcserviceselectronics.co.uk>
<mailto:paul@pcserviceselectro nics.co.uk
<mailto:paul@pcserviceselectronics.co.uk>>> wrote:
If you are doing DMA then a standard ringbuffer is not your
chosen
implementation, you are more likely to be using double buffering
(in software alone or hardware and software).
Considering how I have dealt with SMA, DUAL channel DMA,
multiple DMA
buffers and other techniques since about 1979, on many
systems and
never was
a DMA to Ring Buffer ever considered.
--
Paul Carpenter | pa...@pcserviceselectronics.co.uk
<http://www.pcserviceselectronics.co.uk/> PC Services
<http://www.pcserviceselectronics.co.uk/LogicCell/> Logic Gates Education
<http://www.pcserviceselectronics.co.uk/pi/> Raspberry Pi Add-ons
<http://www.pcserviceselectronics.co.uk/fonts/> Timing Diagram Font
<http://www.badweb.org.uk/> For those web sites you hate
All,BYOB with support for a RingBuffer classes would be all well and good, but an important facet of the problem I outlined is static allocation of the memory used by a class (with the intent of using it for buffering in this case). So I don't think we need to be talking about RingBuffer class, as it just pushes that problem out of HardwareSerial and into some new class. BYOB as I see it looks like this. Add the following two methods to the HardwareSerial class with this signature:void HardwareSerial::setRxBuffer(uint8_t * buf, uint16_t buf_size);void HardwareSerial::setTxBuffer(uint8_t * buf, uint16_t buf_size);... and add two internal pointers to the HardwareSerial class like so:uint8_t * _active_rx_buffer; // default to point at this->_rx_buffer[0]uint8_t * _active_tx_buffer; // default to point at this->_tx_buffer[0]... if you call setRxBuffer it re-wires the class to point active_rx_buffer at buf, and likewise with setTxBuffer and active_tx_buffer. Then just replace all the uses of _rx_buffer and _tx_buffer with their _active counterparts. It would need some testing to be sure, but it would be a fairly low impact to the existing code base I think, and merely extends existing functionality without requirements placed on the build system. It just means application code has to explicitly declare the memory it's going to use, which imho isn't a bad thing, and let the library know about it.Kind Regards,Vic
All,BYOB with support for a RingBuffer classes would be all well and good, but an important facet of the problem I outlined is static allocation of the memory used by a class (with the intent of using it for buffering in this case). So I don't think we need to be talking about RingBuffer class, as it just pushes that problem out of HardwareSerial and into some new class. BYOB as I see it looks like this. Add the following two methods to the HardwareSerial class with this signature:void HardwareSerial::setRxBuffer(uint8_t * buf, uint16_t buf_size);void HardwareSerial::setTxBuffer(uint8_t * buf, uint16_t buf_size);... and add two internal pointers to the HardwareSerial class like so:uint8_t * _active_rx_buffer; // default to point at this->_rx_buffer[0]uint8_t * _active_tx_buffer; // default to point at this->_tx_buffer[0]... if you call setRxBuffer it re-wires the class to point active_rx_buffer at buf, and likewise with setTxBuffer and active_tx_buffer. Then just replace all the uses of _rx_buffer and _tx_buffer with their _active counterparts. It would need some testing to be sure, but it would be a fairly low impact to the existing code base I think, and merely extends existing functionality without requirements placed on the build system. It just means application code has to explicitly declare the memory it's going to use, which imho isn't a bad thing, and let the library know about it.Kind Regards,Vic
Victor,Arduino Zero does not implement a tx buffer for example.- Thomas
On Fri, Jan 13, 2017 at 2:12 PM, Victor Aprea <victor...@wickeddevice.com> wrote:
All,BYOB with support for a RingBuffer classes would be all well and good, but an important facet of the problem I outlined is static allocation of the memory used by a class (with the intent of using it for buffering in this case). So I don't think we need to be talking about RingBuffer class, as it just pushes that problem out of HardwareSerial and into some new class. BYOB as I see it looks like this. Add the following two methods to the HardwareSerial class with this signature:void HardwareSerial::setRxBuffer(uint8_t * buf, uint16_t buf_size);void HardwareSerial::setTxBuffer(uint8_t * buf, uint16_t buf_size);... and add two internal pointers to the HardwareSerial class like so:uint8_t * _active_rx_buffer; // default to point at this->_rx_buffer[0]uint8_t * _active_tx_buffer; // default to point at this->_tx_buffer[0]... if you call setRxBuffer it re-wires the class to point active_rx_buffer at buf, and likewise with setTxBuffer and active_tx_buffer. Then just replace all the uses of _rx_buffer and _tx_buffer with their _active counterparts. It would need some testing to be sure, but it would be a fairly low impact to the existing code base I think, and merely extends existing functionality without requirements placed on the build system. It just means application code has to explicitly declare the memory it's going to use, which imho isn't a bad thing, and let the library know about it.Kind Regards,Vic
Victor,Arduino Zero does not implement a tx buffer for example.- Thomas
On Fri, Jan 13, 2017 at 2:12 PM, Victor Aprea <victor...@wickeddevice.com> wrote:
All,BYOB with support for a RingBuffer classes would be all well and good, but an important facet of the problem I outlined is static allocation of the memory used by a class (with the intent of using it for buffering in this case). So I don't think we need to be talking about RingBuffer class, as it just pushes that problem out of HardwareSerial and into some new class. BYOB as I see it looks like this. Add the following two methods to the HardwareSerial class with this signature:void HardwareSerial::setRxBuffer(uint8_t * buf, uint16_t buf_size);void HardwareSerial::setTxBuffer(uint8_t * buf, uint16_t buf_size);... and add two internal pointers to the HardwareSerial class like so:uint8_t * _active_rx_buffer; // default to point at this->_rx_buffer[0]uint8_t * _active_tx_buffer; // default to point at this->_tx_buffer[0]... if you call setRxBuffer it re-wires the class to point active_rx_buffer at buf, and likewise with setTxBuffer and active_tx_buffer. Then just replace all the uses of _rx_buffer and _tx_buffer with their _active counterparts. It would need some testing to be sure, but it would be a fairly low impact to the existing code base I think, and merely extends existing functionality without requirements placed on the build system. It just means application code has to explicitly declare the memory it's going to use, which imho isn't a bad thing, and let the library know about it.Kind Regards,Vic
--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+unsubscribe@bcmi-labs.cc.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@bcmi-labs.cc.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@bcmi-labs.cc.
For what it is worth:
Personally I for the most part don’t care what the API is, however I do think it is worthwhile to have some simple way for a user to specify per program a way to specify how much memory to use for different resources like devices. And I personally believe in many cases it would be great, if no buffers were allocated for devices I don’t use.
That is suppose on the Teensy world, I develop a simple application for the Teensy LC, which I may use a reasonable amount of memory and Suppose this program does not use Serial2 or Serial3, how do I reclaim the memory that were allocated for this? Likewise for all the Wire objects.
If it were me, I would probably add a couple of methods like: setTXBufferSize() and setRXBufferSize(), which values when you first call begin… This would call so function like malloc. I know many don’t like malloc, I am not one of them, I don’t like free… That is I like the J.C. Wren I think it is fine to do allocations at startup. If there are issues with malloc running into stack, maybe we should update the malloc function to know this and/or have some way to set the max size of the heap.
I believe this aversion to memory allocations hits in many places. Example I am playing around with some Sparkfun Teensyview display(SSD1306) 128x32, and I have another SSD1306 display which is 128x64. If I use the Adafruit library, I have to change their header file to say that I am either using the 32 line one or 64 line one. Why? Mainly to allocate a display buffer for it (plus a few minor init settings) and …
So suppose I wish to handle both? Without using memory allocations, the two main ways of doing this, is:
So in my hacked up version of the Teensyview library, I use malloc to only allocate the size I need.
So again I think it would be great if a simple solution could be found.
Kurt
Is it necessary to have multiple chained buffers with their related inefficiencies?
I'd envisage just an optional argument in serial.begin to attach a buffer of a convenient size.
+1
Please, no pointers.
the problem with hiding buffer allocation is that you need to essentially go throu dynamic memory allocation
Calling "Serial.begin()" is quite frequently done to change the baud-rate .... If the "Serial.begin()" allocates, then you are in trouble if you call the interface too often.
Paul,
Perfect. I’m happy…
--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@bcmi-labs.cc.
On 05/03/2017 08:42 AM, Thomas Roell wrote:
the problem with hiding buffer allocation is that you need to essentially go throu dynamic memory allocation
No, you don't. There's no need to use malloc or new. If begin() is overloaded, you can simply use a static buffer in the case where no buffer is given.
Calling "Serial.begin()" is quite frequently done to change the baud-rate .... If the "Serial.begin()" allocates, then you are in trouble if you call the interface too often.
Then check if memory was already allocated to avoid redundant allocation. Really, how hard is that? Or init to use of a static buffer if the user hasn't provided their own buffer.
Thomas, you've implemented so many features in your custom core library, many of them using quite cunning techniques. Surely you can imagine better implementation!
Several replies, one message...
On 05/03/2017 07:46 AM, Adrian Godwin wrote:
Is it necessary to have multiple chained buffers with their related inefficiencies?
I'd envisage just an optional argument in serial.begin to attach a buffer of a convenient size.
I had imagined a sketch would only call these once, and the implementation would handle multiple calls by simply using the larger or last buffer. But yeah, I can see how the name "addMemory" does imply chaining multiple buffers.
+1
I can’t recall ever calling .begin() a second time for anything but a baudrate change.
From: Tom Igoe [mailto:t.i...@bcmi-labs.cc]
Sent: Wednesday, May 3, 2017 6:28 PM
To: devel...@bcmi-labs.cc
Subject: Re: [Developers] Hardware Serial Buffer Size
That's not a bad idea, Rob.
t.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@bcmi-labs.cc.
--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@bcmi-labs.cc.
--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@bcmi-labs.cc.
--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@bcmi-labs.cc.
--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@bcmi-labs.cc.
--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@bcmi-labs.cc.
--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@bcmi-labs.cc.
--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@bcmi-labs.cc.
--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@bcmi-labs.cc.
--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@bcmi-labs.cc.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+unsubscribe@bcmi-labs.cc.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@bcmi-labs.cc.
I personally like this approach. I think you could easily like with 65K limit.
I assume this requires some form of dynamic memory allocation, which I know that some dislike as it can at times make it difficult to locate issues like, the heap running into the stack.
But I can also see some other equally bad problems with passing in an object or pointer to buffer.
Example suppose you can pass in the buffer like in method, like setStorageForWrite()….
And the user does something like:
Void setup() {
Uint8_t My_Buffer[4000];
Serial.setStorageForWrite(My_Buffer, sizeof(My_Buffer);
…
}
Needless to say having the buffer on the stack first off compiler most likely won’t catch if the value is too large, and 2nd will most likely be clobbered, when the code exits setup.
Or suppose the user creates the buffer one size and passes in the size value larger than the buffer?
Or suppose the user passes the same buffer to setStorageForWrite and setStorageFor Read? Or likewise to multiple objects…
From: Rob Tillaart [mailto:rob.ti...@gmail.com]
Sent: Thursday, May 04, 2017 2:33 AM
To: devel...@bcmi-labs.cc
Subject: Re: [Developers] Hardware Serial Buffer Size
Looking through this discussion I see only small differences in implementation but definitely not in the goals.
Interesting idea…
Can we have a default behavior that “does the right thing” for people without any special buffer requirements, or existing sketches?
t.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@bcmi-labs.cc.
--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@bcmi-labs.cc.
--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@bcmi-labs.cc.
--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@bcmi-labs.cc.
--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@bcmi-labs.cc.
--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@bcmi-labs.cc.
--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@bcmi-labs.cc.
--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@bcmi-labs.cc.
--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@bcmi-labs.cc.
--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@bcmi-labs.cc.
--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@bcmi-labs.cc.
--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@bcmi-labs.cc.
--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@bcmi-labs.cc.
--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@bcmi-labs.cc.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+unsubscribe@bcmi-labs.cc.
Got it, thanks.
And after I hit return I saw the sample API that had been posted. I suppose my remaining question would be, for what cases does this *not* work? As someone else posted, we seem to be converging. Perhaps we’ve converged.
FWIW, I think this is a good approach. It will let me build my manufacturing test jigs a lot more robustly, and my 12-year-old can still make stuff work for school projects…
From: Thomas Roell [mailto:grumpyo...@gmail.com]
Sent: Thursday, May 4, 2017 11:28 AM
To: devel...@bcmi-labs.cc
Subject: Re: [Developers] Hardware Serial Buffer Size
Todd,
t.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@bcmi-labs.cc.
--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@bcmi-labs.cc.
--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@bcmi-labs.cc.
--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@bcmi-labs.cc.
--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@bcmi-labs.cc.
--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@bcmi-labs.cc.
--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@bcmi-labs.cc.
--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@bcmi-labs.cc.
--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@bcmi-labs.cc.
--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@bcmi-labs.cc.
--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@bcmi-labs.cc.
--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@bcmi-labs.cc.
--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@bcmi-labs.cc.
--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@bcmi-labs.cc.
--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@bcmi-labs.cc.
--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@bcmi-labs.cc.