Q&A: BCI51 BASIC Compilers


Here are some of the most common questions which we hear (along with answers!). Please phone or email us if you would like a more detailed technical answer.

What 8051 members does BCI51 support?

There are hundreds of variations of the 8051 family. This includes 8031, 80C31, 80C32, 8751, 8752, 80535, etc, etc. BCI51 supports all 8051 family members as long as they have "movx" external data memory. Usually this means external static RAM. However, some 8051 controllers add 512 or 1024 bytes or more of "movx" data memory. These will work just fine with BCI51.

When will you have Floating Point Math?

We don't have a definite delivery date for floating point math. We do however, have a 32-bit integer math library.

What computer do I need to run BCI51?

Any PC-compatible with a hard disk and MS-DOS 3.0 or later. BCI51 is a DOS program and runs fine under Windows 3.X, Windows95 or Windows NT.

What are Embedded Control Systems?

Embedded control systems are special-purpose computers used in machine and process control.

Do I need external SRAM for data?

BCI51 compiled programs require external data memory. They will not run with just the 128 or 256 bytes of internal data memory common to all 8051 family members.

Does BCI51 support the 87C750/751?

No, since these 8051-subset controllers have no address and data bus, and do not support the assembly code "movx" instruction used by BCI51. They have only 64 bytes of internal data RAM. BCI51 requires some "movx" data memory for all your program's variables, serial I/O buffers, etc.

How much data memory do I need?

BCI51 compiled BASIC programs need about 200 bytes for serial I/O ring buffers, plus space for your BASIC variables. A simple program with a few variables only requires a few hundred bytes of data RAM. Large arrays require memory which is simply equal to the size of the array. For example, an array of 1000 unsigned integers requires 2000 bytes since each unsigned integer occupies 2 bytes (16 bits). Strings are arrays of unsigned characters so a 100 byte string requires 100 bytes of data memory. It's really that simple.

Can my compiled program be stored in internal EPROM?

Yes. BCI51 compiled code can be stored in internal or external EPROM or a mixture of both. Suppose you have an 87C51 with 8 KBytes of EPROM at 0-1FFFH, and 32 KBytes of external EPROM from 2000H to 9FFFH. A 4 KByte compiled program's first 2 KBytes can be stored in the internal EPROM and the rest in the external EPROM.

Can I write my own I/O drivers?

Absolutely! BCI51 was designed to make this straightforward. The compiler includes easy-to-use "hooks" for custom I/O since this is a common embedded system requirement. We include examples (with full, commented source code) of custom drivers including: serial I/O, keypad input, LCD output, serial ADC input, parallel digital input and output, and more. Many of our customers don't need to write a driver, they just use one of the included samples. The provided drivers are written in mixed BASIC and assembly code, and are generally stored as .INC include files. This means all you need to do is "#INCLUDE "filename.inc" in your BASIC program and you have full access to all the features of that driver.

How can I see some sample BCI51 I/O drivers?

Download some of our files here on the internet. The "example files for DPB2E" is especially good. Expand the .ZIP file and look at include files such as KEY_E.INC, the keypad input driver. ADC_E.INC is the 8-bit ADC input driver which uses the TLC549 which is built into DPB2.

Does BCI51 support in-line assembly code?

Absolutely! In fact BCI51 supports assembly code better than many $2000+ C compilers. Surprised? We were too. It turns out that C compiler's optimizers can't deal with in-line assembly code. So in C you either don't do in-line assembly, or you do it once, in a complex multi-step process, compile it, and then use it as an external library. Changing your assembly code requires that you repeat the process. BCI51 is much easier, with no such complications. We include application notes and samples of in-line assembly code. BCI51 has no overhead or penalty of code or speed for the BASIC-to-assembly code switch, so you can do it hundreds of times in your program if you so desire. BCI51's assembly code support is one of it's most popular features.

What processor resources can in-line assembly code use?

In-line assembly code can destructively use the following resources. None of these contain persistent information between BASIC instructions (this may change in a future version of BCI51). Therefore, you do not need to push and pop these resources.

In general, DO NOT use other resources, especially including the following. In special cases where you completely understand the BCI51 runtime library you may be able to violate these rules, but we do not recommend or support such actions, so it will be at your own risk.

Use symbolic labels in assembly code

Save yourself a lot of headaches and always use symbolic references. They are easier to understand and can be changed by editing just the single reference assignment. Here's a snippet of code from an ADC driver.
Notice that you can even define labels for bits within the accumulator or other bit mapped registers. This makes code much easier to read and maintain. You can assign a hard address to a symbol (a fixed I/O address for example) and at least it's in one place which you can find later. Try to never hard-code variable or data addresses. Let the compiler and assembler do their job and keep your code simple and relocatable.
BASIC variables such as MYVAR become prefixed with two underscores in assembly code, as CSO does in the code here. Therefore the BASIC 'MYVAR' becomes the assembly code '__MYVAR'. There are times when you may want an assembly code equate for a similar symbol. In assembly code you could EQU MYVAR and there would be no conflict. This is exactly what we do in this example with CSO_ADR. In this case we wanted a BASIC CSO_ADR as well as an assembly code CSO_ADR. The assembly code label is faster to access than reading the BASIC data CSO_ADR repeatedly. Try to do this as little as possible and only where it really makes your code cleaner or faster, since it is potentially confusing.

unsigned int  CS0_ADR     ; the BASIC variable CS0 register address
unsigned int  DOUT_ADR, DINP_ADR  ; BASIC data out and in registers address


  CS0_ADR = 0F840H                ; hard code the symbol if you need to




#ASM


;----------------------------------------------------------------------------
; Change these bit equates if your hardware bit assignments are different
; This is the only place you need to make the change.
;


DINP_2543 BIT P1.7    ; output from MCU, input to ADC
DOUT_2543 BIT P1.1
CLK_2543  BIT P1.0


ALC_ADC_CS  EQU 1 ; (0) set to chip select the ADC
CS0_ADR   EQU 0F840H    ; the "chip select 0" register address


#ASM_END


Later in the same file:


#ASM


ADC_CS_ON:
  push  ACC
  push  DPL
  push  DPH


  mov     DPTR,#__CS0       ; addr in DPTR
  movx    A,@DPTR                   ; CS0 status, current value
  setb  ACC.ALC_ADC_CS      ; turns output on
  movx  @DPTR, A      ; save the new value
  mov DPTR, #CS0_ADR      ; the i/o address
  movx  @DPTR, A      ; write value to i/o address


  pop DPH
  pop DPL
  pop ACC


  ret


ADC_CS_OFF:
  push  ACC
  push  DPL
  push  DPH


  mov     DPTR,#__CS0       ; addr in DPTR
  movx    A,@DPTR                   ; CS0 status, current value
  clr ACC.ALC_ADC_CS      ; turns output off
  movx  @DPTR, A      ; save the new value
  mov DPTR, #CS0_ADR      ; the i/o address
  movx  @DPTR, A      ; write value to i/o address


  pop DPH
  pop DPL
  pop ACC
  ret


#ASM_END


Can my in-line assembly code access BASIC variables?

Yes! The I/O drivers provided with BCI51 use this feature extensively. We include printed application notes and samples with source code.

Can I run a compiled BCI51 program under BASIC-52?

Yes! We include instructions on how to do this in the manual. Please note that your BASIC-52 target must have "overlaid code and data memory" at the 4000H region. BASIC-52 provides the ability to remap interrupt vectors to the 4000H region in code memory, and BCI51 takes advantage of this. This is necessary to allow BCI51 to load its interrupt vectors which are used for serial I/O, ONTIME and ONEX1 interrupts. Contact your BASIC-52 board vendor or their technical manual to be sure your hardware supports this (many popular BASIC-52 boards do).

Does BCI51 support more than 64K of code?

At the moment, no.

I'm almost at 64K of code. How can I make my program smaller?

Here are a few general suggestions.

  1. Always use the -o option (for optimize) when you compile. This can make your program 3-5% smaller, and has no undesirable side effects.
  2. Minimize use of the INPUT instruction. Due to the many options and exceptions it supports it is quite large and a bit cumbersome. In fact, it was perhaps the messiest BASIC instruction to implement in BCI51. If you must use INPUT, use it as few times as possible. Use it in a subroutine instead of appearing multiple times in your program's main body. Or write your own subroutine with GET to perform the kind of INPUT you need, then see if yours is smaller than the generic BCI51 INPUT. Yes, we are planning to write a more optimized version of INPUT in the future.
  3. In the configuration section, have a #CHECK ISTACK OFF and #TRACE LINE NUMBERS OFF.
  4. Use subroutines to call a common routine from multiple locations in your program, rather than having similar code appear in multiple places. This sounds obvious, but often by looking at your code again you can see places to combine almost-similar code into a shared subroutine.
  5. Simplify the number of explicit strings such as the literal string here: PRINT "This is an explicit string". These explicit strings all take up code space.
  6. Use DO-WHILE or DO-UNTIL loops instead of FOR-NEXT if possible. FOR-NEXT supports a signed index and so is larger and more complex.
  7. Consider writing port I/O routines in in-line assembly code instead of BASIC. If you are manipulating single port bits, this is much simpler and faster in assembly code than in BASIC. We are planning to add some new BASIC library support for bit I/O in the future.
  8. Don't use DATA-READ statements unless absolutely necessary. If you have more than a few dozen DATA statements, use a constant data table instead. We have an example in the Files section.
  9. Simplify your program. Again this sounds so obvious it's almost silly, but many programs develop over a period of time and almost take on a life of their own. Speaking for myself at least, I look at some of my own older code and wonder "what doughbrain wrote this?" Once a program is complete you can often see ways to streamline it.


What is "movx" data memory?

Data memory which can be accessed with the assembly code "movx" for "move external" instruction is sometimes called "movx memory". The movx instruction utilizes the 16-bit address held in the 8051's data pointer as the memory address. The memory can be external to the controller or in some cases (Dallas DS2250/2251/2252, DS87C520/530, Philips 524/528, etc) built into the controller.