Project of programming - scheme on 2003 Documentation of the "PIC simulator" This program is an interface of learning, development and of familiarisation for the microcontrollor 8 bits PIC16F84 made by MICROCHIP. FUNCTIONALITIES : Programming in assembler (PICasm), with definitions of constants. Display of ports A and B, possibility of making them vary for inputs. Display of the main registers of control, the state (sleep/int) and W. Variation of the speed of execution with a knurl at the top. Editiing, saving, loading files of assembler code. Under Linux, with a classic ix86 computer, PORTB cans be displayed on leds (8) connected on the parallel port, on pins (D0 - D7) with an app. 400 Ohm resist. This is managed by a program written in C (output.c), simpler than to make it with scheme there apparently. It takes 2 arguments on the command line, the value to be written and the address in decimal of the port; it owes to be launched as root or have the mode +s and root as owner. Management of interruptions. TODO : Make move the code to see which is being executed. Generation of the binary code of the program and programming by serial port or parallel through a PIC programmer, what would make it an ideal tool of development. Support of the EEPROM. Interruptions during the SLEEP, WatchDog Timer (WDT). Most of OPTION_REG's bits are not taken into account... It is in touch with the WDT. THE PIC : It's 8 bits RISC MTU, it knows 35 instructions, it has 2 I/O ports, one of 5 and one of 8 bits. It can be connected to an eeprom, its usual frequency of work is 4 MHz but can rise if necessary to 10 MHz. The PIC16F84 has 68 bytes of RAM, and a flash memory for the program of 1 kilo words 14 bits wide. The PIC16F83 is the same with 36 B of RAM and 512 words of flash memory. It is usually used in robotics for small robots, for example a follower line robot or one of the schools championship's robot. His competitor in robotics is the Motorola 68HC11 which is more powerful. For more information about the PIC, I included the datasheet taken on the builder's website, which is the file PIC16F84.pdf. Useful parts(parties): Memory organization (file registers) : pages 13 - 17 Inputs / Outputs : pages 21 - 25 Clock and its prescaler : pages 27 - 31 Interrupts : pages 48 - 53 Instructions (list page 56) : pages 55 - 70 The rest concerns not supported fonctionalities or the electronics part and cablage of the µC. REGISTERS : We call registers memory boxes of the PIC, it counts 12 for execution control (p. 14) and 68 for the RAM. The RAM thus begins in 12 (0x0C). All the values hinted are hexadecimal. Simply because FF is worth 255 in decimal, what is the biggest value inside the registers of an 8 bits MCU. We have got an accumulator W which keeps the current variables or results of processes, and an 8 element stack 13 bits wide which keeps in memory the calls to the functions, 13 bits because we've got a program counter (PC) which tells the line of the program which is in execution (PC consisted of 8 bits of the PCL and 5 of the PCLATH); 13 bits to allow an addressing to is 2 kilos words, in the case or there would be 2K words of program in the future version of the PIC (1 K here). Certain registers are only readable, others writing only, others them 2. In my software, nothing forbids to write in a register which is read only. It would be too much complicated and too slow to verify the arguments of all the functions which can write in registers. A programmer reads the documentation about a MCU before programming it, thus he should know any and pay it attention ! The register at 0x01 represents the clock : TMR0. A register is intended has to receive a pointer and an other to indirect addressing from this pointer, it is respectively about 04 FSR and 00 INDF. In registers we can find the input output ports PORTA (05) and PORTB (06) respectively of 5 and 8 bits. One can know if every bit is either configured as an input or an output, by the bits corresponding in registers TRISA and TRISB. For outputs it is 0 and for inputs it is 1. Other registers are displayed on the interface, they are here to indicate different things such as the rise of an interruption, an overflow for an arithmetic operation. FILES : asm_func.scm This file contains all the definitions of the assembler funcs of the PIC. Functions modify at the need all that it is necessary so that in the execution loop of the program we dont mind about that. There are 3 types of instructions as you can see it page 56 of the pdf: - byte oriented file register operations operates on a byte and a memory address. - bit oriented affect or test only a bit of a register. - literal and control operations is to ask a value in the acc, call a subroutine, to return a value, etc. registers.scm We can find here definitions concerning registers and global variables, and the following functions : - PC-ref and PC-set! which reads or writes the PC on 2 registers PCL and PCLATH - TOS and push for the stack, TOS means Top Of Stack, - file-set! and file-ref which have the same behavior that vector-ref and vector-set! as the difference near that they take in argument as well a number as a representation by a string of a number hexa. Finally not usefull because the "compiler" replaces the hex expressions to decimal ones, but for debug and an eventuel change in the behaviour of the program. - is-bit-set? looks if a bit is 1 in a number. - bits-set bit-clear and the others of the same kind put a bit as 0 or 1 in a number. - hexa-string adds a '0' in front of the string of the hex number if it is smaller than 16. - binary-string as same, adds enough 0 so that the binary representation of n has len chars. Useful for PORTA/B which do not make the same size. - remove-0x returns the substring "0c" of "0x0c", which is the syntax used in C to represent a hex number. (string->number str 16) sends back *f if str is not a string of a hexa number, we consider that 0x is in front of. - Z and C give the states of the bits corresponding in the STATUS register. Memory is represented by a vector of size 80 (12 + 68), mem, for fast access. main.scm Here are defined the main functions of the program. Needed variables for the simulation, and the biggest functions : - catch-interrupt sends back the symbol to which the interruption is due, #f if none; the managed interrupts are: TMR0 reached his maximal value if the bit 5 of INTCON is 1, a state change of PORTB on pins 4 5 6 and 7 according to their activation on the TRISB's bits 4 - 7 in input and the bit 4 of INTCON, the bit 0 of the port B, according to its bit of state change and INTCON's bit 4. INTCON's bits are updated even if the interruptions are not activated, and this function returns a value only if the GIE (Global Interrupt Enable bit, INTCON's bit 7) is put as 1. It misses the interrupts which come from the eeprom, my program doesn't supports that at the moment. - runtime is the main execution loop of the program. It refreshes display, increments TMR0, does its job with SLEEP and jumps of interruption, and executes the function of the program. Refreshing parallel port needed to put a change detector, because if it is done each loop for nothing, PLT scheme opens too many files and bugs. We take care also of the case when there is nothing during a loop step, an instruction which makes a conditional jump makes nothing during the 2nd top of clock as described in the datasheet. The two biggest functions: those dedicate to transformation of the assembler code to the scheme funcs defined in asm_func.scm. Fast description: - pre-compile: this function builds 3 types of data: - an association list for the labels of shape ((label . line) ...), indeed we need the line number or rather the branch address of the program which is needed to connect in case of GOTO or CALL instruction. Typically, labels are at the beginning of a line, without anything in front of. - a second AList, this time for the symbols (constants). Indeed, with the keyword EQU, we can define constants (ex: PORTB EQU 0x0C; or 0C). So we have (PORTB . 12) ...) as second struct to easier the work of the "compiler". - to finish, a table which makes the correspondence between a line of the program and a line of the file. It is useful because if there are definitions (EQU), only labels on a line, empty lines or comments, there is a gap. We know then which line of the file we should transform into a scheme expression or to show during the execution. There is as well a special word ORG which takes a number argument x and which forces the next line of code to be has the line x of the program. Useful for interrupts which the branch value of the PC is 004 (we put then "org 004" before the wanted code). Sends back as well the size of the program (in lines) which is required for compilation. There is a syntax to respect, I tried to make something near from what we can find on internet for the PICasm for more comfort : * Labels: Any word in the beginning of line - if the line does not contain EQU - is a label. By agreement, we write them in small letter but it has no importance. it can be only on the line either classically before code : or ¦ |label2 label1 MOVLW a3 ¦ MOVLW a3 ¦ ¦ * Comments: all which follows a ; is considered as a comment until the end of the line. On the other hand what is before is read as code. * Arguments of instructions: for functions with 2 arguments, it is pos- sible to separate the first of the second by a set of commas and spaces; for the destination, we can use the basic arguments of the MCU either as with PICasm, W or w for 0 and f or F for 1. So all these writings are identical: MOVF 0c,1 ¦ MOVF 0x0C f ¦ MOVF 0c, 1 ¦ MOVF 0C , F We can also have argument of a figure from 0 to 7 for binary ops. * Capital letters: It is not necessary to write instructions in capital letters since "Katsmall T. Wise" from the PLT mailing list told me how to do. * Numbers format: numbers written in the code are interpreted in hexadecimal, we have to different ways to write them : raw product (4f) or C formated (0x4F). Capital letters here are not important, we can also use the format we want as long as it makes a size of two chars like hx4f or $h4f or whatever. We also have in hand a usefull special shape for numbers, the pattern bit which allows to write directly binary instead of hexa; for that, it is necessary to prefix with b and to put among '. Ex: MOVLW b'11110000' It should not have spaces there, and necessarily 8 bits. * Name of the symbols: symbols (and labels) should not contain any ',' nor ';'. We can use same names for labels and constants. * End of file: the file (or the code in the editor) should finish by a line feed, except when the last line is not an instruction. I did not found how to add it automatically... - compile: by basing itself on the data of pre-compile, it builds a table representing the memory of the program of the PIC, in which we find instructions ready to be evaluated (by eval). If a function is not recognized by the parsage, it puts NOP instead. The runtime function is launched in a thread, to be able to stop it easily. interface-dessin.scm We define the interface's window geometry and all the drawings there. I use the bitmap-canvas% of the "memento of the schemer" so that the window remembers what is drawn in it if we crosse something above. draw-registers-content is called every loop for refresh the displayed data. It redraws everything, it would be too much complicated to refresh only those which changed. It would be necessary to redo it in more beautiful, with a true separator and scrollbars between the ram and the middle part, to be able to shrink the window. interface-editeur.scm Definitions for the editor, the buttons above. Not big things finally. All classics tricks there in MrEd interfaces. BUG: it seems that saving a file modifies it in the sense of the raw text, but we do not not see it in the editor. interface-inputs.scm The little window defined here opens on click on the button INPUTS of the main window. Buttons are active only if the bits they represent are configured in input. We re-read it every opening. Thus it is necessary to close it and open again to refresh. BUG: when one clicks several times on INPUTS, it opens several windows. How to redraw it then? opcode.scm It was made to generate the binary code which has to go into the microcontrollor but I did not get the time to make this part. From the compiled code it mustn't be complicated. In the file there are the binary codes of every instruction, which are called the opcode. It must be filled with the arguments. USE : First, it is necessary to load the main.scm file in DrScheme and execute it. The window of the program opens and it is ready to work. For the configuration of the parallel port if need, see first lines of interface-dessin.scm (conf:use-parport and mon-port-parallele for address). On the left, we find the 68 registers of the RAM. The address is written next to each box. In the middle, there is the working reg W, the program counter which indicates the number of the line which is going to be executed or which is doing, down, TMR0 the clock. Then, there are some registers interessants in binary because we need to see every bit. Finally leds, the 2 first symbolize the standby state and if an INTCON flag is at 1, which means that an interruption has occured, or that she would have been able to if they are not activated. Leds below are ports A and B. Buttons: Exit closes the window. INPUTS opens the window with check-box to simulate inputs on ports. RUN/STOP launches the simulation or stop it, we can make vary the speed with the slider. STEP executes the line specified by the PC and stops then. RESET is the equivalent of the hardware reset which puts back registers into the original state, or wakes up the MCU from a SLEEP. load loads a file in the editor. Save saves the contents of the editor in a file. Make "compile" the code contained in the editor. You can load a file or to type a new, before beginning the simulation, you have to click make to load it in the memory of the virtual PIC. Then play with RUN/STOP and STEP for controll its execution, and if needed, INPUTS to make vary inputs. EXAMPLES count.asm This file was found on the net, it's only showing a binary counter on PORTB. I removed 4 calls to pause and I shrank it because it needed several hours or days to go out of it. It is indeed the problem with this software, it is slow. Both lines list p=16F84 and radix hex are covered because of the org 0x000, otherwise we would see them in the code and it would makes problems. helloLed.asm Also found on the net, it shows how to use the binary shape b'xxxxxxxx'. It is only putting 170 on PORTB and looping infinitely. int.scm This program lights the leds of the PORTB a short moment if an interruption is detected. It waits for them in the infinite loop, it is better to put the speed in a small value if you want to see something. When an interruption comes, there are 4 tops of clock without instruction. To summarize what is said higher, interruption are raising when we make vary the input 0 of the PORTB, that this on rising or downward dependly of the 6th bit of OPTION_REG, when we make vary the bits 4 5 6 and 7 of the PORTB, those in theory in any sense but bizarrely that works only on rising (BUG), and when TMR0 reaches FF. The PC is then loaded with has 004 and stays in the routine of interruption until the RETFIE. It is an amusing program to test the interruptions :) chenillard.asm Just a go from right to left of two leds. They ignite all at the end. my-big-example.asm That complicates... We makes a multiplication of two data read on PORTB. It is better to go slowly even more in step, otherwise we only have not enough time to enter the data which we wish. For corser the whole, we have an interruption if we try to bring in an odd number - totally useless but it is for the beauty of the thing. The mult is called by CALL, we find the result in the register RES. The data A and B are not modified, we use I for operations controll. There is though what enjoy itself, in spite of what misses (see TODO on top). I am rather satisfied with the result, especially that it asked a lot of work. Hoping that the doc is clear enough... Vincent HOURDIN - 2003 vinvin @ vinvin.dyn...