Jump to content

jsobell

EstablishedMember
  • Content Count

    15
  • Joined

  • Last visited

Community Reputation

0 Neutral

About jsobell

  • Rank
    Newbrie

Contact Methods

  • MSN
    jason@sobell.net
  • Website URL
    http://
  • ICQ
    0

Profile Information

  • Location
    Melbourne, Australia
  1. That's almost correct On the PIC18 we can't use the latch to read the data (such as status bits), as it always reflects the last written value, so we still need to use the data register. All in all, we need to specify three ports in the setup, which is what the code I'm emailing you does. It's annoying to have to change the configuration options and add a parameter, creating a minor break in backwards compatability, but there has to be a way to specify separate data read port and data write ports. Cheers, Jason
  2. On which PIC chip? As I've already shown several times, this is PIC16 only, and does not work on the PIC18 with it's latch register, hence why I emailed you version that worked on both. I get this strange feeling of deja-vu... Please see my posting from "Jul 5 2005, 02:42 PM" Cheers, Jason
  3. Not sure if you're still looking for a solution, but I did quite a lot of this stuff long ago... Optical encoders use slots with offset optical sensors so that the pulses to two pins are in different sequences depending on direction. e.g. Clockwise might be: A B 0 0 1 0 1 1 0 1 : Anticlockwise: A B 0 0 0 1 1 1 1 0 : The most obvious method of using one optical output (e.g. 'A') to trigger an interrupt and the other ('B') to detect direction does not work well in practice because if the sensor is at any speed then the direction can't be read in time and 'B' will already have changed to its next state. The simplest solution is to create a simple circuit with a latch that triggers on the rising edge of the 'A' input, and locks the state into the 'B'. This means you can still use 'A' to trigger an interrupt, but 'B' is always correctly reflecting the direction. This way you may lose a few pulses if the control is 'spun' too quickly, but at least it won't start detecting as reverse Hope this helps, and that it's not too late for someone to find useful Cheers, Jason
  4. There's still nothing changed in the provided source to address this issue, and given that it's fairly standard to use a single 8-bit port for LCD display control, perhaps it should be rectified in the SourceBoost supplied version? At the moment I have to replace the installed lcd_driver.h after every upgrade with my own to fix the bug. Cheers, Jason
  5. Hmm, I think this is a mute point, as the latter problems you describe are unsolvable on the PIC16, and is the reason the latch was introduced on the PIC18. Yes, I understand that, but Dave's response was to suggest simply replacing 'PortA' with 'LatA', but this does not work in the common scenario where the port is shared. I posted a very simple solution for this situation that works with PIC16s with separate control/data ports, and with PIC18s with either separate or combined. Hence we have a solution that is still target independant, but works in more situations than before. If someone can code up the solution to the PIC16 using a shared port, then that's great, and will only involve some compiler conditional code adding a few lines and one variable. I would do it myself, but I don't have any PIC16s at the moment (and the emulator is not consistent with the hardware port read/writes). Whatever happens, it is not going to resolve the issue you mention above where a developer writes directly to the port, but we know we can't do anything about this, so it's probably best to simply document it in the template and let the developer beware. Cheers, Jason
  6. I have a few suggestions with regards to usability: - Implement a keypress for switching between debug and edit mode without having to click a button on the toolbar. - Ability to have more than one instance of each plugin displayed at the same time. - Configuration options on plugins for high/low state. e.g. simulating a button that is normally high is not supported. - Provide a 'plugin' window into which the plugins are placed. Having them dock in the main editor window is messy, and the ability to minimise the plugin window when it's not is use would be nice. - Develop a plugin that takes the name of a text file containing a list of hex or binary values to input to a port. This could then be used to simulate serial or parallel data. Cheers, Jason
  7. Obviously, but this does not work if Data and Control are on the same port. The problem is in modifying the Data port in nibbles, where 'OR'ing in a new value will cause an internal Read/Write to set the new bits. When the Read is performed, it reads the control bits as being zero, despite the fact they are actually high. Therefore, you *must* use the latch or you must OR in the saved state of the control pins, otherwise they will be forced back to low. Target independence is only possible if you allow for the fact that PIC18s and PIC16s handle their ports differently. Check the Microchip data sheets and see at the port circuitry for the differences. Cheers, Jason
  8. It's been posted to the 'Bug Reports' section here, and seems to me to be a fundamental and serious bug (which is why an acknowledgement/confirmation/"no Jason, you're an idiot" response would be nice ) *Edit* Ah, the bug in the LCD code is that if you try and display an unsigned integer using %u then it is always displayed as signed (only without the '-' symbol). I wanted to display numbers >32768, so had to fix it. I'll email you the fixes instead of posting in here. */Edit* Cheers, Jason
  9. Also, the code shown is optimised out to say i = 0xFFFE If you code it in separate statements: unsigned int x1 = 0xffff; unsigned int x2 = 0xffff; unsigned int x3 = x1 + x2; then the carry flag will in fact be set correctly, but I certainly wouldn't put any dependency on it staying that way. Out of interest, how would you normally code to catch this? In most C implementations you could use a check against the result because you have Long datatypes, but what would you do in BoostC? Cheers, Jason
  10. You could set the new bit immediately after the shift if the carry is set, effectively doing a byte rotate. e.g. (and I've not tested this) RLF myreg,1 BNC noset BSF myreg,0 noset: Alternatively, check the bottom bit first, and set the carry flag so it gets shifted in correctly. Both would use a similar number of cycles. Alternatively, (and better still), use a PIC18 instead and you have the RRNCF and RLNCF functions that don't go via the carry flag. You must use two bytes. If the carry is set, you have an extra bit to set in the lowest bit of the next byte. The result can only ever be a max of 9 bits, as 0xFF+0xFF=0x1FE. Cheers, Jason
  11. From what I can see in the spec sheet, the latch register gets around the 'high load' issue. When I run the ICD2 emulator, it does indeed read the pins as being low, even when they are actually high (and that's with a 1.5K resistor to the base of a transistor!), so the latch register is the only one with the current state shown correctly on the PIC18. I do remember the old 'store a copy of the register in RAM' issue on the PIC17 series, and I assume that's one reason the latch was introduced on the PIC18. Most posts regarding this from MicroChip state that the latch should be used instead of the port register, so unless problems arise with the PIC16 then I suspect my solution may be the 'officially correct' method. I've looked at the code created, and the following appears: data |= d & 0xF0; 012A 0EF0 MOVLW 0xF0 012C 1411 ANDWF LCD_RawWri_00005_arg_d, W 012E 128C IORWF LCD_RawWri_00005_1_data, F This looks correct, as a single read is being performed from variable d, with a single immediate OR to the destination port (data), so this is not where the problem lies (although it was a good potential problem point). Once the char to int casting bug is fixed then I'd like to contribute back another fix for the led_driver.h that allows display of signed and unsigned values correctly. Who is managing this stuff? Should I email the changes to someone instead of posting them in here? Cheers, Jason
  12. When a char is cast to an integer, too many bytes are being copied, as shown in this example: char x=1; 05A8 0E01 MOVLW 0x01 05AA 6E0E MOVWF main_1_x int y; y = (int)x; 05AC 6E0F MOVWF main_1_y 05AE 500F MOVF main_1_x+D'1', W 05B0 6E10 MOVWF main_1_y+D'1' Location main_1_x+D'1' should obviously be set to zero when casting from and unsigned char, or 0xFF if from a signed char with the topmost bit set. This is quite a serious problem, as the current implementation may appear fine as long as mem+1 is empty (for unsigned chars or signed chars<128), but in a live environment... I found it when calling a function that takes an integer: lprintf("%06d", x); which is the equivalent of lprintf("%06d", (int)x); On the PIC16, the top byte is always cleared, whether the char is signed or not: char x=-1; 0003 30FF MOVLW 0xFF 0004 1283 BCF STATUS, RP0 0005 1303 BCF STATUS, RP1 0006 008C MOVWF main_1_x int y; y=x; 0007 008D MOVWF main_1_y 0008 018E CLRF main_1_y+D'1' IDE version: 6.03 Compiler: BoostC Compiler version: 6.03 Target device: PIC18F452, PIC16xx OS: WinXP Cheers, Jason
  13. Sorry, I should have marked them. Search for ReadDataPort, which is the variable/template option I added throughout. I also changed the suggested configuration options: //#define LCD_ARGS 2, /* Interface type: mode 0 = 8bit, 1 = 4bit(low nibble), 2 = 4bit(upper nibble) */ \ // 1, /* Use busy signal: 1 = use busy, 0 = use time delays */\ // LATD, PORTD, TRISD, /* Write Data port, Read Data port, and data port tris register */ \ // LATD, TRISD, /* Control port and control port tris register */ \ // 3, /* Bit number of control port is connected to RS */ \ // 2, /* Bit number of control port is connected to RW */ \ // 1 /* Bit number of control port is connected to Enable */ I suspect this is all a PIC18x specific issue, as the PIC16 doesn't use the concept of a latch register. I also believe it shows a problem in the SourceBoost emulator which seems to always reflect the last byte written to the port, hence why the LCD program works fine with the LCD display plugin in emulation mode but not in practise. Cheers, Jason
  14. Well, after struggling for two days with bizzare issues with a simple LCD display, I finally found the problem. I'm not sure if this is common to all PICs, and it's been many years since I did any amount of PIC programming, but I had extreme problems interfacing to the display due to the way the template is coded for reading data back in 4bit mode. If you choose to use a single port to write to a display, it makes sense to set all of the ports to one port, in my case PortD. The problem arises that if you use a function such as: data |= d & 0xF0; then the existing value is read from the port, then written back. Unfortunately, if there are output pins on that port then the data read does not reflect the existing values, so your existing outputs get stomped on. Using the latch register (latd) in place of the port (portd) fixes the problem, but the latch can't be used to read the values when the port is reversed for status information, so two different variables are required to specify the port for reading (portd) and writing (latd). I've modified the template to reflect this change, and would appreciate someone checking to see if this makes sense or if I've completely missed the point and was misusing the template in the first place (Dave?). I can't test it with the other pin setups (8 bit mode and 4bit lo nibble), but I assume those sections are now corrected too. Ah well, at last my display is alive... Now to find something to use it for. Cheers, Jason p.s. A file attach option on the forum might be nice... ------------Code follows----------- //////////////////////////////////////////////////////////////////////////// // LCD with HD44780 drive chip //////////////////////////////////////////////////////////////////////////// // Author(s): David Hobday, Pavel Baranov // Date 15 November 2004 // // Copyright (c) 2004-2005 Pavel Baranov // Copyright (c) 2004-2005 David Hobday // Copyright (c) 2004 Andrew Smallridge // // // How to use - by David Hobday // ============================ // These must be define before template header file is included // Remember when using LCD in 4 bit mode you must connect to the LCDs DB4-DB7 pins // // *** For a list of functions, see the END of this file. // // The time delays used in the code should mean that it will work on PIC18 with // 40MHz clock without any changes. // // The example below (which would work on a PIC16F84) operates the display // in 4bit mode and requires the following connections: // RS to RA3 // R/W to RA2 // E to RA1 // DB0 to None // DB1 to None // DB2 to None // DB3 to None // DB4 to RB4 // DB5 to RB5 // DB6 to RB6 // DB7 to RB7 // // // Add the following after #include <system.h> in you source file: // //#define LCD_ARGS 2, /* Interface type: mode 0 = 8bit, 1 = 4bit(low nibble), 2 = 4bit(upper nibble) */ \ // 1, /* Use busy signal: 1 = use busy, 0 = use time delays */\ // LATD, PORTD, TRISD, /* Write Data port, Read Data port, and data port tris register */ \ // LATD, TRISD, /* Control port and control port tris register */ \ // 3, /* Bit number of control port is connected to RS */ \ // 2, /* Bit number of control port is connected to RW */ \ // 1 /* Bit number of control port is connected to Enable */ // //#include <lcd_driver.h> // include the LCD template code // // // Revisions // ========= // // V1.10 David Hobday 03/03/2005 // ============================= // 1) Improved documentation in file // 2) Changed delays to delay_10us for usage on target with clock <= 4MHz // 3) Changed template to make more friendly and obvious // // V1.11 18/03/2005 // David Hobday // 1) Fixed operation with PIC18 - template arguments of incorrect type // 2) Tested with PicDem2Plus board (4MHz PIC16F877/PIC18F452) // 3) Added lcd_gotoxy function. // 4) Added option to use display busy bit or time delays // 5) Added overloaded lprintf function for ROM string // 6) Added overloaded lprintf function to output numbers supported formats: // "%d" - decimal // "%X" - hex // "%b" - binart // example: display binary number six digits, '0' as file character. // lprintf( "val:%06b", numb ); // 7) Other improvements/cleanup. // // // V1.11 David Hobday 25/03/2005 // ============================= // 1) Fixed bug with lprintf( "test:%d", 0 ); not printing a 0. // 2) Added a few more comments in lprintf( const char*, int ) code // // // V1.12 Jason Sobell 03/07/2005 // ============================= // 1) Fixed bug when data and control ports are the same (introduced ReadDataPort) // //////////////////////////////////////////////////////////////////////////// char writeDelayType; //////////////////////////////////////////////////////////////////////////// // LCD Commands ( Refer to LCD Data Sheet ) //////////////////////////////////////////////////////////////////////////// #define clear_lcd 0x01 // Clear Display #define return_home 0x02 // Cursor to Home position #define entry_mode 0x06 // Normal entry mode #define entry_mode_rev 0x04 // Normal entry mode -reverse direction #define entry_mode_scroll 0x07 // - with shift #define entry_mode_scroll_rev 0x05 // reverse direction #define system_set_8_bit 0x38 // 8 bit data mode 2 line ( 5x7 font ) #define system_set_4_bit 0x28 // 4 bit data mode 2 line ( 5x7 font ) #define system_set_reset 0x30 // Reset code #define display_on 0x0C // Display ON - 2 line mode #define display_off 0x08 // Display off #define set_dd_line1 0x80 // Line 1 position 1 #define set_dd_line2 0xC0 // Line 2 position 1 #define set_dd_ram 0x80 // Line 1 position 1 #define write_data 0x00 // With RS = 1 #define cursor_on 0x0E // Switch Cursor ON #define cursor_off 0x0C // Switch Cursor OFF #define cursor_blink_on 0x0F // Cursor plus blink #define cursor_shift_right 0x14 // Move cursor right #define cursor_shift_left 0x10 // Move cursor left #define display_shift_right 0x1C // Scroll display right #define display_shift_left 0x18 // Scroll display left #define WriteNoDelay 1 #define WriteControlled 0 // Interface type #define LCD_8_BIT_MODE 0 #define LCD_4_BIT_LO_NIB_MODE 1 #define LCD_4_BIT_HI_NIB_MODE 2 // These macros make susequent code more readable, but can seem a little confusing #define _LCD_RawWriteNibble LCD_RawWriteNibble <InterfaceType, UseBusy, DataPort, ReadDataPort, Data_PortTris, CtrlPort, Ctrl_PortTris, RS, RW, E> #define _LCD_RawWriteNibbleInline LCD_RawWriteNibbleInline <InterfaceType, UseBusy, DataPort, ReadDataPort, Data_PortTris, CtrlPort, Ctrl_PortTris, RS, RW, E> #define _LCD_Read LCD_Read <InterfaceType, UseBusy, DataPort, ReadDataPort, Data_PortTris, CtrlPort, Ctrl_PortTris, RS, RW, E> #define _LCD_WaitForNotBusy LCD_WaitForNotBusy <InterfaceType, UseBusy, DataPort, ReadDataPort, Data_PortTris, CtrlPort, Ctrl_PortTris, RS, RW, E> #define _LCD_Write LCD_Write <InterfaceType, UseBusy, DataPort, ReadDataPort, Data_PortTris, CtrlPort, Ctrl_PortTris, RS, RW, E> #define _LCD_FunctionMode LCD_FunctionMode <InterfaceType, UseBusy, DataPort, ReadDataPort, Data_PortTris, CtrlPort, Ctrl_PortTris, RS, RW, E> #define _LCD_DataMode LCD_DataMode <InterfaceType, UseBusy, DataPort, ReadDataPort, Data_PortTris, CtrlPort, Ctrl_PortTris, RS, RW, E> #define _LCD_RawWrite LCD_RawWrite <InterfaceType, UseBusy, DataPort, ReadDataPort, Data_PortTris, CtrlPort, Ctrl_PortTris, RS, RW, E> #define _LCD_ClockOut LCD_ClockOut <InterfaceType, UseBusy, DataPort, ReadDataPort, Data_PortTris, CtrlPort, Ctrl_PortTris, RS, RW, E> #define _LCD_TEMPL template < unsigned char InterfaceType,\ unsigned char UseBusy,\ unsigned int DataPort, unsigned int ReadDataPort, unsigned int Data_PortTris,\ unsigned int CtrlPort, unsigned int Ctrl_PortTris,\ unsigned char RS, unsigned char RW, unsigned char E> _LCD_TEMPL inline void LCD_FunctionMode( void ) { volatile bit rs@CtrlPort.RS = 0; } _LCD_TEMPL inline void LCD_DataMode( void ) { volatile bit rs@CtrlPort.RS = 1; } inline void LCD_CycleMakeupDelay() { // Enable cycle time must be > 1000ns total for both reading and writing // LCD_SetupDelay + LCD_EnablePulseDelay + LCD_HoldupDelay + LCD_CycleMakeupDelay >= 1000ns // 200 + 500 + 100 + 200 >= 1000ns // This delay is required to meet the Sharp data sheet total cycle time of > 1000ns // @40MHz this is 2 instructions asm nop asm nop } inline void LCD_EnablePulseDelay() { // PWEH > 460ns on Sharp data sheet // @40MHz this is 5 instructions asm nop asm nop asm nop asm nop asm nop } inline void LCD_SetupDelay() { // tAS > 140ns min on Sharp data sheet // @40MHz this is 2 instructions asm nop asm nop } inline void LCD_HoldupDelay() { // tAS > 10ns min on Sharp data sheet // @40MHz this is 1 instructions asm nop } _LCD_TEMPL char LCD_Read() { char d; volatile unsigned char data@DataPort, tris@Data_PortTris, readdata@ReadDataPort; volatile bit rw@CtrlPort.RW, e@CtrlPort.E; if( InterfaceType == LCD_4_BIT_HI_NIB_MODE ) { // upper nibble input tris |= 0xF0; rw = 1; // set reading mode // first high nibble LCD_SetupDelay(); e = 1; LCD_EnablePulseDelay(); // d = data & 0xF0; // read data d = readdata & 0xF0; // read data e = 0; LCD_HoldupDelay(); LCD_CycleMakeupDelay(); // then low nibble LCD_SetupDelay(); e = 1; LCD_EnablePulseDelay(); //d |= data >> 4; d |= readdata >> 4; e = 0; LCD_HoldupDelay(); LCD_CycleMakeupDelay(); } if( InterfaceType == LCD_4_BIT_LO_NIB_MODE ) { // lower nibble input tris |= 0x0F; rw = 1; // set reading mode // first high nibble LCD_SetupDelay(); e = 1; LCD_EnablePulseDelay(); d = readdata << 4; e = 0; LCD_HoldupDelay(); LCD_CycleMakeupDelay(); // then low nibble LCD_SetupDelay(); e = 1; LCD_EnablePulseDelay(); d |= readdata & 0x0F; e = 0; LCD_HoldupDelay(); LCD_CycleMakeupDelay(); } if( InterfaceType == LCD_8_BIT_MODE ) { // port input tris = 0xFF; rw = 1; // set reading mode LCD_SetupDelay(); e = 1; LCD_EnablePulseDelay(); d = readdata; e = 0; LCD_HoldupDelay(); LCD_CycleMakeupDelay(); } return d; } _LCD_TEMPL void LCD_RawWriteNibble( char d ) { // Note: this function is duplicate below, but declared inline. // this is to reduce stack depth usage // Note: this function is above, but declared inline. // this is to reduce stack depth usage //volatile unsigned char data@DataPort, tris@Data_PortTris; volatile unsigned char data@DataPort, tris@Data_PortTris; volatile bit rw@CtrlPort.RW, e@CtrlPort.E; if( InterfaceType == LCD_4_BIT_HI_NIB_MODE ) { // port upper nibble output rw = 0; // set writing mode LCD_SetupDelay(); tris &= 0x0F; data &= 0x0F; data |= d & 0xF0; e = 1; LCD_EnablePulseDelay(); e = 0; LCD_HoldupDelay(); LCD_CycleMakeupDelay(); } if( InterfaceType == LCD_4_BIT_LO_NIB_MODE ) { // port upper nibble output rw = 0; // set writing mode LCD_SetupDelay(); tris &= 0xF0; data &= 0xF0; data |= d >> 4; e = 1; LCD_EnablePulseDelay(); e = 0; LCD_HoldupDelay(); LCD_CycleMakeupDelay(); } } _LCD_TEMPL inline void LCD_RawWriteNibbleInline( char d ) { // Note: this function is above, but declared inline. // this is to reduce stack depth usage volatile unsigned char data@DataPort, tris@Data_PortTris; volatile bit rw@CtrlPort.RW, e@CtrlPort.E; if( InterfaceType == LCD_4_BIT_HI_NIB_MODE ) { // port upper nibble output rw = 0; // set writing mode LCD_SetupDelay(); tris &= 0x0F; data &= 0x0F; data |= d & 0xF0; e = 1; LCD_EnablePulseDelay(); e = 0; LCD_HoldupDelay(); LCD_CycleMakeupDelay(); } if( InterfaceType == LCD_4_BIT_LO_NIB_MODE ) { // port upper nibble output rw = 0; // set writing mode LCD_SetupDelay(); tris &= 0xF0; data &= 0xF0; data |= d >> 4; e = 1; LCD_EnablePulseDelay(); e = 0; LCD_HoldupDelay(); LCD_CycleMakeupDelay(); } } _LCD_TEMPL void LCD_RawWrite( char d ) { volatile unsigned char tris@Data_PortTris, data@DataPort; volatile bit rw@CtrlPort.RW, e@CtrlPort.E; if( InterfaceType == LCD_4_BIT_HI_NIB_MODE ) { // output upper nibble, then lower nibble bit flag = 0; do { _LCD_RawWriteNibbleInline( d ); flag = !flag; d <<= 4; } while( flag ); } if( InterfaceType == LCD_4_BIT_LO_NIB_MODE ) { // output upper nibble, then lower nibble bit flag = 0; do { _LCD_RawWriteNibbleInline( d ); flag = !flag; d <<= 4; } while( flag ); } if( InterfaceType == LCD_8_BIT_MODE ) { // port b output rw = 0; // set writing mode tris = 0x00; data = d; LCD_SetupDelay(); e = 1; LCD_EnablePulseDelay(); e = 0; LCD_HoldupDelay(); LCD_CycleMakeupDelay(); } } _LCD_TEMPL inline void LCD_WaitForNotBusy() { // volatile bit rs@CtrlPort.RS; bit old_RS = rs; volatile bit rs@CtrlPort.RS; bit old_RS = rs; rs = 0; while( _LCD_Read() & 0x80 ); // wait while busy set rs = old_RS; } _LCD_TEMPL void LCD_Write(char d ) { volatile bit rs@CtrlPort.RS; if( UseBusy == 1 ) { // wait until display Not busy before sending next data if ( writeDelayType == WriteControlled ) _LCD_WaitForNotBusy(); _LCD_RawWrite( d ); } else { _LCD_RawWrite( d ); // give time to complete if ( writeDelayType == WriteControlled ) { if( !rs && (d == return_home || d == clear_lcd) ) delay_ms( 2 ); // return_home takes more time than other instructions to execute else delay_10us( 5 ); // 50us - enough time for normal command execution - clear and home need longer!! } } } _LCD_TEMPL void LCD_Clear() { _LCD_FunctionMode(); _LCD_Write( clear_lcd ); // clear display _LCD_Write( return_home ); } _LCD_TEMPL void LCD_Setup( void ) { // set control port bits used to output volatile bit trisRS@Ctrl_PortTris.RS, trisRW@Ctrl_PortTris.RW, trisE@Ctrl_PortTris.E; trisRS = 0; trisRW = 0; trisE = 0; writeDelayType = WriteNoDelay; // no delays in data writes delay_ms(16); // Power up delay _LCD_FunctionMode(); if( InterfaceType == LCD_4_BIT_HI_NIB_MODE ) { // Reset sequence as described in data sheets _LCD_RawWriteNibble( system_set_reset ); delay_ms(5); // min delay here of 4.1 ms _LCD_RawWriteNibble( system_set_reset ); delay_10us(100); // min delay here of 100us _LCD_RawWriteNibble( system_set_reset ); // LCD busy flag is valid from this point onwards if( UseBusy == 1 ) _LCD_WaitForNotBusy(); else delay_10us( 5 ); // standard command delay time _LCD_RawWriteNibble( system_set_4_bit ); if( UseBusy == 1 ) _LCD_WaitForNotBusy(); else delay_10us( 5 ); // standard command delay time writeDelayType = WriteControlled; _LCD_Write( system_set_4_bit ); } if( InterfaceType == LCD_4_BIT_LO_NIB_MODE ) { // Reset sequence as described in data sheets _LCD_RawWriteNibble( system_set_reset ); delay_ms(5); // min delay here of 4.1 ms _LCD_RawWriteNibble( system_set_reset ); delay_10us(100); // min delay here of 100us _LCD_RawWriteNibble( system_set_reset ); // LCD busy flag is valid from this point onwards if( UseBusy == 1 ) _LCD_WaitForNotBusy(); else delay_10us( 5 ); // standard command delay time _LCD_RawWriteNibble( system_set_4_bit ); if( UseBusy == 1 ) _LCD_WaitForNotBusy(); else delay_10us( 5 ); // standard command delay time writeDelayType = WriteControlled; _LCD_Write( system_set_4_bit ); } if( InterfaceType == LCD_8_BIT_MODE ) { // Reset sequence as described in data sheets _LCD_RawWrite( system_set_reset ); delay_ms(5); // min delay here of 4.1 ms _LCD_RawWrite( system_set_reset ); delay_10us(10); // min delay here of 100us _LCD_RawWrite( system_set_reset ); // busy flag is valid from this point onwards if( UseBusy == 1 ) _LCD_WaitForNotBusy(); else delay_10us( 5 ); // standard command delay time _LCD_RawWrite( system_set_8_bit ); if( UseBusy == 1 ) _LCD_WaitForNotBusy(); else delay_10us( 5 ); // standard command delay time writeDelayType = WriteControlled; // use busy } _LCD_Write( entry_mode ); _LCD_Write( display_on ); _LCD_Write( set_dd_ram ); } _LCD_TEMPL void LCD_Printf( const char *lcdptr ) { char pi = 0, c; _LCD_DataMode(); while( 1 ) { c = lcdptr[pi++]; if ( !c ) return; if ( c == '\n' ) { _LCD_FunctionMode(); // move to start second line _LCD_Write( set_dd_ram + 0x40 ); _LCD_DataMode(); } else _LCD_Write( c );// Display on LCD } } _LCD_TEMPL void LCD_Printf( rom char *lcdptr ) { char pi = 0, c; _LCD_DataMode(); while( 1 ) { c = lcdptr[pi++]; if ( !c ) return; if ( c == '\n' ) { _LCD_FunctionMode(); // move to start second line _LCD_Write( set_dd_ram + 0x40 ); _LCD_DataMode(); } else _LCD_Write( c );// Display on LCD } } _LCD_TEMPL void LCD_Printf( const char *lcdptr, int val ) { unsigned char pi = 0, bi, c, fill, baseOrBits, sign, mask; unsigned char buff[ 10 ]; // max length allow is 9 bit pad; _LCD_DataMode(); while( 1 ) { c = lcdptr[pi++]; if ( !c ) return; switch( c ) { case '\n': _LCD_FunctionMode(); // move to start second line _LCD_Write( set_dd_ram + 0x40 ); _LCD_DataMode(); break; case '%': c = lcdptr[pi++]; if ( !c ) return; // Next character if zero indicates that we should zero fill output if ( c == '0' ) { fill = '0'; c = lcdptr[pi++]; if ( !c ) return; } else fill = ' '; // Next character if valid digit indicates field width if( c > '0' && c <= '9' ) { pad = 1; bi = c - 48;; c = lcdptr[pi++]; if ( !c ) return; } else { pad = 0; bi = sizeof( buff ) - 1; } // Next character indicates the radix (number base) sign = 0; switch( c ) { case 'd': if( val < 0 ) sign = '-'; case 'u': baseOrBits = 10; // base ten, divide by ten per digit break; case 'X': baseOrBits = 4; // base 16, requires a 4 bit shift per digit mask = 0x0F; break; case 'b': baseOrBits = 1; // base 16, requires a 1 bit shift per digit mask = 0x01; break; default: return; // no radix } // null terminate, then reverse fill string buff[ bi ] = '\0'; bit first = true; while( bi ) { bi--; if( val || first ) { first = false; if( baseOrBits == 10 ) { c = (unsigned char)(val % baseOrBits); val /= baseOrBits; if( c & 0x80 ) c = 0 - c; // negative numbers } else { c = val & mask; val = ((unsigned int)val) >> baseOrBits; } if( c > 9 ) c += 55; // convert to hex digits character A-F else c += 48; // convert to digit character 0-9 } else { if( sign && (bi == 0 || fill != '0') ) { c = sign; sign = 0; } else c = fill; } buff[ bi ] = c; if( pad == 0 && val == 0 && sign == 0 ) break; } // output string to display while( 1 ) { c = buff[ bi ]; if( !c ) break; _LCD_Write( c );// Display on LCD bi++; } break; default: _LCD_Write( c );// Display on LCD break; } } } _LCD_TEMPL void LCD_GotoXy( char x, char y ) { _LCD_FunctionMode(); unsigned char offset = (y << 6) + x; _LCD_Write( set_dd_ram + offset ); } _LCD_TEMPL void LCD_Function( char func ) { _LCD_FunctionMode(); _LCD_Write( func ); } //////////////////////////////////////////////////////////////////////////// // Helpers that hide template arguments //////////////////////////////////////////////////////////////////////////// // low level functions #define lcd_write LCD_Write<LCD_ARGS> #define lcd_waitfornotbusy LCD_WaitForNotBusy<LCD_ARGS> #define lcd_read LCD_Read<LCD_ARGS> #define lcd_funcmode LCD_FunctionMode<LCD_ARGS> #define lcd_datamode LCD_DataMode<LCD_ARGS> // high level functions - these all set function or data mode as required #define lcd_setup LCD_Setup<LCD_ARGS> #define lprintf LCD_Printf<LCD_ARGS> #define lcd_clear LCD_Clear<LCD_ARGS> #define lcd_gotoxy LCD_GotoXy<LCD_ARGS> #define lcd_function LCD_Function<LCD_ARGS>
  15. Hi, I'm struggling to work out how I can program my in-circuit PIC18 from the command line via the Olimex ICD2 compatible board. It works fine with MPLAB, but is there any info around on integration with SourceBoost IDE? Am I missing something in the RTFM department? Cheers, Jason
×
×
  • Create New...