Oshonsoft v Sourceboost Well, it's a sad day at Nerd Towers, as we've had to wave goodbye to our favourite PIC compiler, Oshonsoft's PIC18 Simulator - for the next few projects at least. It's a great compiler, the best simulator bar none, makes USB/HID coding a doddle, but - sadly - it's lack of support means we've started to outgrow it. The number of chips supported is starting to look a little thin, now we've discovered these great little PICs - 16F1825 The thing is, to use some of the newer Microchips, we're going to have to use a different compiler. MPLAB (even version X) is still a mess and difficult to use (not to mention sloooow) so we've been looking at alternatives. Jason from BuildBrighton suggested SourceBoost which, at £60 for a full licence, looks pretty good value. Now here's the dilemma: Stick with a BASIC-based compiler for USB/HID and switch between languages/compilers for other stuff, or slowly upgrade everything to a C-based compiler/language and leave Oshonsoft behind for good? Posted by Chris Holden at 13:16 3 comments Email ThisBlogThis!Share to TwitterShare to FacebookShare to Pinterest Labels: oshonsoft, sourceboost Wednesday, 14 December 2011 Serial-to-parallel LCD display driver Amazingly we managed to get a working serial character LCD in under an hour today! Just followed the schematics at http://embedded-lab.com/blog/?p=30 and converted the code example they gave into Oshonsoft Basic. Fired it up and there we go - a blinking "Hello World!" message using just three pins on the microcontroller. The only real issue we had was that the contrast isn't brilliant; instead of a 10K linear pot, we've gone and used the first potentiometer that was to hand (a 1M logarithmic pot!) If, like us here at Nerd Towers, you're an Oshonsoft fan, here's the code listing to get everything working: AllDigital Config PORTC = Output configuration: Symbol enablepin = PORTC.0 Symbol clockpin = PORTC.1 Symbol datapin = PORTC.2 declarations: Dim i As Byte Dim lcdi As Byte Dim lcdbyte As Byte Dim lcdbytetosend As Byte Dim rs As Bit Dim flag As Byte Dim mask As Byte init: Gosub initialiselcd loop: lcdbytetosend = 32 Gosub writelcddata lcdbytetosend = "H" Gosub writelcddata lcdbytetosend = "e" Gosub writelcddata lcdbytetosend = "l" Gosub writelcddata lcdbytetosend = "l" Gosub writelcddata lcdbytetosend = "o" Gosub writelcddata lcdbytetosend = 32 Gosub writelcddata lcdbytetosend = "W" Gosub writelcddata lcdbytetosend = "o" Gosub writelcddata lcdbytetosend = "r" Gosub writelcddata lcdbytetosend = "l" Gosub writelcddata lcdbytetosend = "d" Gosub writelcddata lcdbytetosend = "!" Gosub writelcddata WaitMs 4000 lcdbytetosend = 0x01 'clear screen Gosub writelcdcommand WaitMs 2000 Goto loop End writelcdnibble: Low enablepin Low clockpin If rs = 1 Then High datapin Else Low datapin Gosub toggleclockpin 'shift in 4 bits mask = 8 For lcdi = 1 To 4 flag = lcdbyte And mask If flag = 0 Then Low datapin Else High datapin Gosub toggleclockpin mask = ShiftRight(mask, 1) Next lcdi 'now strobe the clock one more time because ST+SC are tied Gosub toggleclockpin 'toggle the enable pin to "flush" the data into the lcd Low datapin High enablepin Low enablepin Return toggleclockpin: 'toggle the clock pin High clockpin Low clockpin Return writelcddata: rs = 1 Gosub senddata Return writelcdcommand: rs = 0 Gosub senddata Return senddata: lcdbyte = ShiftRight(lcdbytetosend, 4) Gosub writelcdnibble lcdbyte = lcdbytetosend And 15 Gosub writelcdnibble Return initialiselcd: For i = 1 To 3 WaitMs 50 lcdbytetosend = 0x20 Gosub writelcdcommand Next i WaitMs 50 lcdbytetosend = 0x28 '4 bits, 2 lines, 5x7 font Gosub writelcdcommand WaitMs 50 lcdbytetosend = 0x0c 'display on, no cursors Gosub writelcdcommand WaitMs 50 lcdbytetosend = 0x06 'entry mode auto-increment Gosub writelcdcommand WaitMs 50 lcdbytetosend = 0x01 'clear screen Gosub writelcdcommand Return Posted by Chris Holden at 21:59 0 comments Email ThisBlogThis!Share to TwitterShare to FacebookShare to Pinterest Labels: character lcd, hitatchi 44780, oshonsoft, serial, shift register Wednesday, 30 November 2011 Serial/UART communication between two PICs (18F and 16F) It's taken a long time and a lot of different approaches to get even simple serial communication between two PICs working. Perhaps hampered a little by using two different PICs (a 16F and an 18F series chip) but that really shouldn't make any difference. Serial/UART communication shouldn't be platform dependent! We've tried serial/UART, SPI, I2C and even bit-banging and each time got different (non-working) results. It's too much to go into in this blog post, so we're just going to describe how we actually got a working prototype: The first thing to note is that although we're using one of our favoured 18F4550 PICs, we couldn't use the USB and UART together. So for this experiment, we're reading the data back off our 18F (master) chip via serial, using the excellent PICKit2 programmer and software. In our first (failed) attempt at creating pic-to-pic communication, we had our 16F (slave) device monitoring it's input pins and simply broadcasting the results as an 8-byte message over UART. The idea was for the 18F (master) chip to read this serial stream at intervals, find the start of the message and decode the rest of it, so that it knows the state of the slave chip. In theory this sounds fine. In practice, sending more than about 4 bytes to the 18F (master) chip caused it to lock up on the Hserin command. We even tried connecting the PICKit2 to the RX pin on the 18F and removed our slave chip altogether. Our tests confirmed the same thing happening - if we sent one or two bytes at a time to the 18F from the PICKit2 terminal, it successfully received them and sent a response message back. If we sent more than about five bytes at a time, the 18F simply stopped responding - apparently locking up at the point where it reads in the serial data (we proved this by switching an LED on just before the Hserin command, and turning it off again immediately after). So it appears that we have a set-up whereby we can receive data from our slave, one byte at a time, but the master can't simply "dip in" to a serial stream being "broadcast" by the slave. After reading through the datasheet, it seems that the 18F has only a two (or was it four) byte buffer so blasting more bytes into the buffer than it can handle is causing some sort of buffer overrun error. We need some way of getting the master chip to ask for data, one byte at a time. This is what we came up with: The master chip sends a pin high then requests a byte from the serial buffer. The slave chip monitors the state of the "handshaking" line. When the line goes high, and the previous line state is low, this represents a request from the master, so send one byte. Because we're using hardware UART on the master chip, after the line goes high, the code waits until a byte has arrived in the serial buffer. Because the slave only sends a byte on a low-to-high transition on the handshaking pin, we don't have to worry about buffer under-runs or errors in the master chip. Slave code '4Mhz external clock Define CONF_WORD = 0x3f31 Define CLOCK_FREQUENCY = 4 AllDigital Config PORTB = Input Config PORTD = Input Config PORTC = Input Config PORTA = Input declarations: Dim linestate As Bit Dim lastlinestate As Bit Dim a1 As Byte Dim a2 As Byte Dim a3 As Byte Dim a4 As Byte Dim a5 As Byte Dim xorval As Byte Dim bytecounter As Byte init: WaitMs 50 Hseropen 9600 WaitMs 50 linestate = 0 lastlinestate = 0 bytecounter = 1 loop: 'all the slave does is read a whole load of input pins 'and write the response back to the master. The master chip 'will decide which "row" is live, this chip just takes all 'the "column" data and sends it back to the master. 'RA0-5 'RB1-7 'RC0-5 (6&7 are TX/RX) 'RD0-7 'RE0-2 'this should give us 6+7+6+8+3 = 30 inputs a1 = PORTA And 63 '(mask off bits 7+6) a2 = PORTB And 254 '(make off bit 0, handshake line) a3 = PORTC And 63 a4 = PORTD a5 = PORTE And 7 'now stream the values as a response back to the slave 'all messages begin 255,255 (since this sequence is not 'possible in the input stream because we bitmask bytes 1,3,5) linestate = PORTB.0 If linestate = 1 And lastlinestate = 0 Then 'the host chip has asked for another byte of data 'create the checksum value xorval = 0 xorval = xorval Xor a1 xorval = xorval Xor a2 xorval = xorval Xor a3 xorval = xorval Xor a4 xorval = xorval Xor a5 xorval = xorval And 127 'decide which byte of the message to send '(the host has to ask for each message eight times for all 8 bytes) Select Case bytecounter Case 1 Hserout 255 Case 2 Hserout 255 Case 3 Hserout a1 Case 4 Hserout a2 Case 5 Hserout a3 Case 6 Hserout a4 Case 7 Hserout a5 Case 8 Hserout xorval bytecounter = 0 EndSelect bytecounter = bytecounter + 1 Endif lastlinestate = linestate Goto loop End Master code AllDigital declarations: Dim a1 As Byte Dim a2 As Byte Symbol lineshake = PORTA.0 Config PORTA.0 = Output init: Low PORTA.0 WaitMs 200 Hseropen 9600 WaitMs 200 loop: Gosub getnextbyte 'two 255 = start of message Hserout 255 Hserout 255 Hserout a1 Goto loop End getnextbyte: 'to get the next byte, we send the lineshaking 'line high - this tells the slave to "release" 'another byte. Once we have this byte, we drive 'the lineshaking pin low to say we're done High lineshake Hserin a1 Low lineshake Return After connecting up the slave to the master (the TX pin of the slave into the RX pin of the master, and RA.0 on the master to RB.0 on the slave) we did actually start receiving intelligible data from the master. So it looks like we've (finally) cracked pic-to-pic communication over serial. It's probably a bit slower than it needs to be (since the master has to "poll" each byte from the slave) but it's fast enough for what we want - and once we crank the baud rate up from 9600 to about 57600, or even 115200, it should be more than quick enough to scan an entire game board (of not more than 16 x 28 = 448 squares) at a reasonable rate. Posted by Chris Holden at 23:53 11 comments