Jump to content

J5 / A7 (RE2) as "status input pin" problem - solved


ilmenator
 Share

Recommended Posts

Hi all,

I have an application which uses an external SRAM card as memory extension. It is based on the schematic from TL - see this post: http://www.midibox.org/forum/index.php?topic=4140.msg27685#msg27685. For the CARD PRESENT status of the card (= is it connected to the core or is the card disconnected) I am currently using one DIN pin. The detection mechanism is very simple: there is one pin on the card connector that is connected to ground by the card whenever it is inserted, and which is connected to +5V via a pullup resistor whenever no card is inserted.

This works well and gives me the correct status whenever the status changes, that means whenever I connect or disconnect the memory card. BUT the problem is that I am not interested in the change of the status, but in the status itself: upon powering up the core, I have no means of detecting whether the card is connected or not, because the DIN mechanism is checking for transitions.

Now, I am trying to use pin A7 of J5 (that is RE2 of the core 18F452) in the same manner: I have a pullup of 100k against +5V, and whenever the card is inserted, the pin is drawn to ground. To my knowledge, the C code necessary to initialize the input of Port E is very simple:

/////////////////////////////////////////////////////////////////////////////
// This function is called after startup to initialize the SRAM
/////////////////////////////////////////////////////////////////////////////
void SRAM_Init(void) __wparam
{
	// disable the ADC which allocates the analog pins
	// only needed if controls pins are connected to port A
	ADCON1 = 0x07;
...

	// configure RE2 as input for reading SRAM card status
	// Pin RE.2 = input
	TRISEbits.TRISE2 = 1;

	return;
}
Then I only have to check the status of that pin regularly, e.g. in [tt]Tick(void)[/tt], using something like:
app_flags_t.SRAM_CARD_STATUS = PORTEbits.RE2;

which could be defined the same way as the DISPLAY_UPDATE_REQ flag in the sdcc_skeleton demo code.

So why did I put this into "Troubleshooting" and not "Programming in C"? Well, it does not work this way, and I tried to meter the potential of the RE2 pin using a multimeter. In fact, that pin is always at ground level, no matter if the card is connecting the pin to ground or not! So... is the pullup resistor too large (100 kOhm)? 

I also measured the resistance accross the resistor (with the circuit powered off, of course). It reads about only 20 kOhm when the "circuit" is connected to pin RE2. If I disonnect it from there (pulling the J5 plug), then the resistor value reads 100 kOhm as it should be. If I connect the card, then the resistance across the pullup drops further down to about 2 kOhm. J5 disconnected and card inserted gives me 28 kOhm across the 100 kOhm pullup. I am sure there is no short circuit, that is why I really don't get any further here. Any suggestions? Do I need to do something more to the core / the PORTE input? Do I need to change the pullup's resistor value to get to a decent potential at pin RE2?

???  ???  ???

Best regards, ilmenator

SRAM_card_workbench.JPG

Link to comment
Share on other sites

Hey illy

You probably should make sure the port/latch are clear before setting the input, but I don't think it's a big deal...

Now I'm having a bit of trouble visualising the circuitry so I might have missed something here, but:

(pulling the J5 plug), <SNIP>  If I connect the card, then the resistance across the pullup drops further down to about 2 kOhm.

J5 disconnected and card inserted gives me 28 kOhm across the 100 kOhm pullup.

Is it 2 or 28kOhm?

I could really go a rough circuit diagram... or maybe some Z's, it is 0130 after all  :-\

Link to comment
Share on other sites

Hi stryd,

it is 2k when J5 is connected to the core and the SRAM card is inserted. It is 28k when J5 is not connected and the card inserted. I was thinking of maybe I have a "ground loop" problem or something like that, as I am using both the J5 and the J15 connectors from the core, both carrying +5V and ground.

BUT in fact J15 only delivers to the LCD connected also to J15. Both 74HCT573 are supplied via J5. So I would suppose that if I disconnect J5 completely, then the +5V pin of that IC (pin 20) should have a potential of 0V, that means ground level - but indeed I measure 3.6V without the SRAM card inserted, possibly coming from where??? If I insert the SRAM card, that voltage drops to 3.0V, which is the backup battery voltage - if I remove the battery, strangely enough I still measure 1.35V.

It's a real mess, and it's hard to come up with a drawing of the circuit, because I wonder how much of that battery backup circuit of the SRAM card is relevant here - and how that might look like.  :-\

Yet, I was wondering why it works flawlessly using a DIN input pin then?? I will try to dig deeper (and hopefully to make more sense to all of you readers out there  ;D).

Thanks, ilmenator

Link to comment
Share on other sites

Hi Ilmenator,

are you sure, that TRISE isn't change back to another value somewhere else, e.g. within your SRAM driver? Because for me it sounds like the output driver of the pin is enabled (TRISE flag set to 0)

You could use MIOS Studio to read out the SFR value, just open the debug window and start a read transaction from address 0xf96

Best Regards, Thorsten.

Link to comment
Share on other sites

Hi Thorsten,

I am almost sure that it is set as an input pin, because TRISE is only touched once in the SRAM_Init routine and then left alone.

	// put PortE in output mode
	// Pin RE.0 = output
	TRISEbits.TRISE0 = 0;
	// Pin RE.1 = output
	TRISEbits.TRISE1 = 0;
	// configure RE2 as input for reading SRAM card status
	// Pin RE.2 = input
	TRISEbits.TRISE2 = 1;
Yet, when I read from address 0xf96 as you suggested, MIOS Studio reads
0F96: 01 
Done
which should mean that RE.0 is configured as input and RE.1 and RE.2 as outputs, if I read the PIC18FXX2 documentation correctly (DS39564C-page 97). Now, if in the SRAM_Init routine I write this:
	// put PortE in output mode
	// Pin RE.0 = output
	TRISEbits.TRISE0 = 0;
	// Pin RE.1 = output
	TRISEbits.TRISE1 = 1;
	// configure RE2 as input for reading SRAM card status
	// Pin RE.2 = input
	TRISEbits.TRISE2 = 0;
then I can actually measure the toggle of the potential on input pin RE.2 when connecting/disconnecting the card. If I use MIOS Studio to read from address 0xf96, I get
0F96: 05 
Done

If I manually write 0x04 into 0xf96 using MIOS Studio, the potential on Pin RE.2 also toggles between ground and +4.61 V or so.

All that basically means success and your assumption is right. But then I wonder whether maybe the pin enumeration within MIOS got scrambled or something like that? Also I still cannot read the status of RE2 correctly, which might also be related to some pin scrambling in the wrapper or so?

I would be glad if you could check this, or tell me how I could possibly check my suspicion?

Best regards, ilmenator

Link to comment
Share on other sites

Hi Ilmenator,

it seems that the register definition in pic18f452.h is not correct:


extern __sfr __at 0xf96 TRISE;
typedef union {
        struct {
                unsigned :1;
                unsigned TRISE0:1;
                unsigned TRISE1:1;
                unsigned TRISE2:1;
                unsigned :1;
                unsigned IBOV:1;
                unsigned OBF:1;
                unsigned IBF:1;
        };
} __TRISEbits_t;
[/code] I would expect:
[code]
extern __sfr __at 0xf96 TRISE;
typedef union {
        struct {
                unsigned TRISE0:1;
                unsigned TRISE1:1;
                unsigned TRISE2:1;
                unsigned :1;
                unsigned PSPMODE:1;
                unsigned IBOV:1;
                unsigned OBF:1;
                unsigned IBF:1;
        };
} __TRISEbits_t;

Could you please check, if it works with this change?

This header file is not part of MIOS, but has been copied from an SDCC include directory. Maybe there is a newer version in the meantime.

Best Regards, Thorsten.

Link to comment
Share on other sites

Yes, the corrected version does its job as it's supposed to.  :D So what I have now is the correct potential on the input pin RE2 of the PIC. Still I cannot read the status with my code. Here is what I do:

/////////////////////////////////////////////////////////////////////////////
// This function is called after startup to initialize the SRAM
/////////////////////////////////////////////////////////////////////////////
void SRAM_Init(void) __wparam
{
	// clear PortE
	PORTE = 0x00;

	// disable the ADC which allocates the analog pins
	// only needed if controls pins are connected to port A
	ADCON1 = 0x07;
...
	// put PortE in output mode
	// Pin RE.0 = output
	TRISEbits.TRISE0 = 0;
	// Pin RE.1 = output
	TRISEbits.TRISE1 = 0;
	// configure RE2 as input for reading SRAM card status
	// Pin RE.2 = input
	TRISEbits.TRISE2 = 1;

	return;
}
Then in main.h I modified the Global Types section like this:
/////////////////////////////////////////////////////////////////////////////
// Global Types
/////////////////////////////////////////////////////////////////////////////

// status of application
typedef union {
  struct {
    unsigned ALL:8;
  };
  struct {
    unsigned DISPLAY_UPDATE_REQ:1;  // requests a display update
    unsigned SRAM_CARD_STATUS:1;	// if set, SRAM card is present
  };
} app_flags_t;
In main.c I used the Tick() function to check the status and request a display update - I know that the display update should not be requested from here, but it's a quick and dirty solution.
/////////////////////////////////////////////////////////////////////////////
// This function is called by MIOS in the mainloop when nothing else is to do
/////////////////////////////////////////////////////////////////////////////
void Tick(void) __wparam
{
  app_flags.SRAM_CARD_STATUS = PORTEbits.RE2;
  app_flags.DISPLAY_UPDATE_REQ = 1;
}
Finally, in DISPLAY_Tick() I print the status on the LCD like this:
/////////////////////////////////////////////////////////////////////////////
//  This function is called in the mainloop when no temporary message is shown
//  on screen. Print the realtime messages here
/////////////////////////////////////////////////////////////////////////////
void DISPLAY_Tick(void) __wparam
{
  if( !app_flags.DISPLAY_UPDATE_REQ )
    return;

  // clear request
  app_flags.DISPLAY_UPDATE_REQ = 0;

  if( app_flags.SRAM_CARD_STATUS ){
	MIOS_LCD_CursorSet(0x60);
	MIOS_LCD_PrintCString("Card OK");
  } else{
	MIOS_LCD_CursorSet(0x60);
	MIOS_LCD_PrintCString("No Card");
  }
}

I think that this code should work - any thoughts on this?

Thanks very much, ilmenator

Link to comment
Share on other sites

I'm not 100% sure, but I remember that I had some issues with bit copies like this one:

app_flags.SRAM_CARD_STATUS = PORTEbits.RE2;

what happens, when you display the PORTE value directly on screen? E.g., within the DISPLAY_Tick() function

Best Regards, Thorsten.

Link to comment
Share on other sites

Hi Thorsten,

I replaced

  app_flags.SRAM_CARD_STATUS = PORTEbits.RE2;
with
  if( PORTEbits.RE2 ){
    app_flags.SRAM_CARD_STATUS = 1;
  }else{
    app_flags.SRAM_CARD_STATUS = 0;
  }

,

now everything works as expected.  ;D

I left a comment in the C programming section of the Wiki: http://www.midibox.org/dokuwiki/doku.php?id=c_tips_and_tricks_for_pic_programming#sdcc_bugs_workarounds

As always Thorsten: thanks for that hint!

Best regards, ilmenator

Link to comment
Share on other sites

I have some more mysteries to solve before going public with this baby...

One is best formulated in a question: what happens if I "hijack" the address and data bus of a device that is supposed to be the master of these buses with only one "receiver" attached? Do I need to separate the original master from the buses whenever the "hijacker" tries to access it? More specifically: will a second "bus master device" (i.e. a PIC using address and data bus for communication with SRAM memory) present any harm to the first one? I have a feeling that I do not want to try this out...

So I have looked into the 74HCT646 bus transceiver to act as a bus separator. I know that there are special bus switch devices like e.g. Fairchild or IDT 3245 bus switches, but I have not found a way of purchasing them in lower quantities here in Germany. Has anybody used the 74HCT646 before?

Best regards, ilmenator

Link to comment
Share on other sites

Mate if you can get that to work you're doing better than me... but that's not hard hahahaha! Seriously though, if I can do ANYTHING to help, if you need parts or funding or anything let me know!

I was trying to get that going for the vX, so I could have one core for the CS, which would read/write to the database in SRAM, and another core which would read/write from the SRAM and act as the sequencer core (brains). Obviously you need a connection between the cores to ensure exclusivity when read/write operations on the buss are required, and it needs to be pretty fast so MB-Link didn't seem the right method. I was thinking about using a free pin on each core to negotiate the master core.

Because the two cores would be connected to each other by their LCD busses I wasn't sure of the right way to make sure that they didn't interfere with each other, so maybe the 646 is the right way to go... Of course because my app is a sequencer I'm also concerned about having to drive too many pins and slowing things down... Not sure how that's going to effect you though, but I thought it worth mentioning.

Hopefully some hardware guru will chime in any minute ;)

Link to comment
Share on other sites

Stryd,

thanks for offering help - I will surely get back to you one of these days.

My application is not time critical, so I think I could establish a protocol that insures that only one device accesses the bus at a time. In the original machine that I am trying to "hijack" this is done via the Card Status flag - so the synth (you might be able to guess what I am trying to do by now  ;D) only accesses the buses when a card is present. If I simulate that status flag with my application, I should be able to prevent the synth from accessing the bus. I will further try to physically remove the buses from the synth via the 646 to minimize the risk of damage to the synth. Whenever the status flag is set by my application, it means it will no longer have control over the buses, but the synth takes over. There is one critical moment, that is when my application wants to get back the bus control. It needs to set the status flag accordingly, which should not be done when the synth is trying to write to the card. But on the other hand, you would not unplug the card physically from the synth when you know that the synth is writing your sounds to the card, either, or would you?  ;D

Best regards, ilmenator

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

×
×
  • Create New...