New Install: Adobe Bridge CS6 Crashes immediately

This problem has wasted hours for me so I’ll document it here.

Though I purchased CS6 (back when you could), I never actively used it – I always preferred CS2.

Recently I was forced to upgrade my photoshop system from XP to Windows 7. After getting Photoshop CS2 up and running on the new Win 7 system, I found some really irritating issues, particularly the fact that CS2 will print ONLY to the default printer. If your photo printer is not the default, you have to set it to default before starting photoshop.

My primary reason for staying with CS2 was the extensive set of hotkeys that largely went away in either CS4 or CS6. These days I just don’t use photoshop that heavily so I decided I could live without my old hot-key environment rather than F*&)ing with setting the default printer.

I got photoshop CS6 up and running without much ado; however, everytime I attempted to start Bridge it would immediately crash and the beginning of the info dump contains:

 Problem Event Name: APPCRASH
 Application Name: Bridge.exe
 Application Version: 5.0.2.4

There are many reports of Bridge crashes and even those that match these, there was no solution that worked for me.

Finally I stumbled upon the thread:

https://forums.adobe.com/thread/1360817

Way down toward the bottom was the answer for me: temporarily rename a registry tree:

I know it’s old thread but here is my solution:

1) Run regedit application (from search menu, type regedit)

2) Find “HKEY_CURRENT_USER\Software\Adobe\Bridge” key.

3) If the key exists, then rename the “Bridge” key to something else like “xBridge”.

4) Then run the Adobe Bridge CS6, it should be running fine now.

5) Restore back the renamed “Bridge” key in regedit.

From my analysis it has something to do with settings loading conflict with previous version of Bridge CS you had installed.

That did the trick. I rename the tree ‘Bridge’ to ‘xBridge’, start Bridge.exe and it starts correctly. Exit Bridge, rename the tree ‘xBridge’ back to ‘Bridge’, and Bridge.exe still starts correctly.

Advertisements
Posted in c-photo | Tagged | Leave a comment

Woof Off! – A Device to Control an Out-of-Control Barking Dog

A friend came to me a few months ago asking for help building something to stop his neighbor’s barking dog. I’ve been having the same problem for a few years now, so I was definitely interested.

I’m fortunate enough to have good neighbors, but they are not dog people. In fact, they never really wanted this dog. How they ended up with two dogs is a story not worth going into. But, the upshot is one dog barks, they really have no control over it, and see something like a bark collar as being cruel.

So I have to put up with a dog barking under my office window on a regular basis.

I had looked at some commercial products but just never felt they were going to work for me. So I did nothing. Now that someone else wanted something I had a little more incentive to figure out if ultrasonic sound might really be effective.

There are various circuits on the web that produce an ultrasonic (40kHz) signal. Mine is just a variation of these. I use a 555 timer to produce the signal, then an LM-386 to amplify it.

Some circuits just drive the speaker directly from the 555. I feel like a get a somewhat stronger signal from the LM-386, but not so much that I would say it is an absolute must.

Here is my schematic:


Schematic notes:

I use terminals to connect power and speakers which show up a little confusingly on the schematic. A diode protects the circuit from reversed polarity. I have found I can drive 2 speakers from the LM386 which effectively nearly doubles the output power so there are terminals for 2 speakers.

This circuit was tested using 12V. It will run on 9V, but the output volume will not be quite as high.

During initial testing of the circuit, I setup the 555 to emit a frequency I could hear, around 12KHz. Once I was ready for real testing, I needed speakers that would actually work at 40KHz. Regular speakers don’t.

I found this ultrasonic speaker on ebay which also has the advantage of being water proof:

I purchased mine from:

https://www.ebay.com/itm/6X-High-Power-Ultrasonic-Transmitter-Mosquito-Rat-Repellent-Speaker-Horn-40KHz/253259498948?ssPageName=STRK%3AMEBIDX%3AIT&_trksid=p2057872.m2749.l2649

The speaker was installed and the 555 set to produce 40kHz, I could no longer hear the signal. Was it really working? My dogs are not a good test subject as they are both deaf.

I ended up purchasing a set ultrasonic transmitter / receivers like this from Amazon:

I simply clipped my oscilloscope probes to one of the ultrasonic receiver to see how strong the signal was. This allowed me to do comparative testing to see if my output was stronger or weaker.

Once I had what I thought was a functioning unit, I needed to do a field test to see if dogs would really pay any attention to it. I produced a nice clean breadboard unit I could carry around.

This unit doesn’t match the final schematic exactly. To provide 12V, I used 2X 4LR44 6V batteries which fit perfectly in a single AA battery holder.

I tested this on a handful of dogs. Some hear it, some don’t (or at least pay no attention). The barker most definitely heard it. That gave me the green light to produce a final unit.

Using VeeCad, I converted the schematic into a strip board layout:

See How to use VeeCAD Stripboard Editor with CadSoftĀ Eagle for more information.

I had forgotten how slow it is to build a circuit using stripoard. But it is still cheaper than PCB and way faster than waiting for the PCB to be created and mailed to me.

The final stripboard looked pretty nice:

I decided I could mount the unit inside my house and mount the speakers to the window. The ‘barker’ stands about 6′ from this window when she barks. By keeping the electronics inside the house, that solves weather proofing and power issues.

To control this, I wanted a remote control key fob that would work from my office. I purchased a cheap Chinese unit:

https://www.ebay.com/itm/12V-DC-ON-OFF-remote-control-wireless-12V-output-Relay-Switch-Kit/161723609765?ssPageName=STRK%3AMEBIDX%3AIT&_trksid=p2057872.m2749.l2649

The key fob batteries died IMMEDIATELY (I got around 10 key presses on either fob before it was dead). Irritating, but the vendor credited me the cost of new batteries.

Once the remote was working it was just a matter of cramming it all into a plastic project box and setting up some external jacks and a power LED.

Red Green says duct tape is the handy man’s secret weapon. I say it is Velcro tape and hot glue. Seems like every project ends up using one or both.

The last step was to slap a cheap graphic on the project!

Once the final unit was set up, I watched the dog when I turned the unit on. She would immediately perk up her ears and look directly at it. Even 1/2 way across the neighbor’s yard she could clearly hear it.

Using Woof Off!

One would be tempted to just turn this on and subject the barker continuously to the sound. However good that might feel to you (and I did consider it myself), it is the wrong way to go about getting effective results. Remember: it isn’t the dog’s fault it barks. It is the owner’s fault.

To effectively use Woof Off, you want to use it as a training tool. That’s going to take some time on your part, but you have a better chance of getting good results if you train the dog properly.

During the training period, I kept my key fob with me at all times. The dog is allowed to bark for about 5 seconds (you have to be realistic here – dogs are going to bark, you can’t expect zero tolerance).

If the dog continues to bark after about 5 seconds, I turn Woof Off! on for 10 seconds and switch it back off. And I repeat until the dog finally quits.

Within 3 days of training, the barks became tentative. You could just hear in the tone she wasn’t sure she really wanted to bark.

I’m now about 2 weeks into ‘training’. She still barks some, particularly when people walk by, but having her sit under my window ‘woofing’ every 5 seconds for an hour or more no longer occurs. The situation is back to being reasonable again.

 

Posted in c-electronics | Tagged , | 1 Comment

Poor Man’s Conductive Pre-Compliance Testing

I want to do some pre-compliance testing on Scammer Jammer. I have an inexpensive spectrum analyzer to do radiated testing. Conductive testing requires more expensive equipment.

First, you need an LISN device and, in my case, it needs to be connected to 110V and I’ve learned trying to do that myself is expensive and dangerous. Plus, the testing is, according to this, is in the frequencies 150kHz to 30MHz. My spectrum analyzer STARTS at 30MHz. There is no way for me to test frequencies that low with equipment I can afford.

While researching pre-compliance testing, I stumbled across this article:

http://www.compliance-club.com/archive/keitharmstrong/emc_testing2.html

According to that article, you can wrap an extension cord around an AM radio, connect it to the power mains, connect the other end to the device under test, and then you can hear any EMI on the radio.

I tried using a radio in this manner, and sure enough found Scammer Jammer’s LCD back-light circuitry was creating a lot of noise.

The following video shows how I setup the radio and tested Scammer Jammer:

I am using a Radio Shack DX390 General Coverage Receiver or (Sanjean ATS 808). A normal radio’s AM band covers 540kHz to 1210kHz. My radio also supports the long wave band which cover 150kHz to 540kHz.

https://www.hkvstar.com/images/articles/588_ISM_Bands.jpg

 

Posted in c-electronics | Tagged | Leave a comment

Scammer Jammer Telemarketer Call Blocker

I’ve not posted much in the past 2 years because I’ve been busy on the project that was, in part, due to the research that I ended up posting here.

I didn’t want to post anything specifically about this project because I really didn’t know where I was going with it. I still don’t. But I’ll at least admit it exists šŸ™‚

A little intro – I detest telephone solicitors of any kind. When I was a director of networking services for an S&P 500 company, my phone would ring all day with cold calls. I would then go home where it would continue ringing with credit card offers, etc. I have grown to detest my phone ringing unless it is someone I know.

To add to my personal distaste of telemarketers, there has been a fast rise of telephone-based scams on seniors. My aging relatives call me asking if they were right in hanging up on Microsoft, Apple, the IRS, etc. I realized it was just a matter of time until one or more of them was taken.

I’ve looked at existing telemarketer call blockers and none of them were really going to buy much. They all work on the same basic concept – you blacklist individual numbers. A few would allow some kind of wild card, but that is rare. More importantly either they didn’t stop the phone from ringing, OR they intercepted caller ID so that it would not make it to my handset. Really not worth the money in my opinion.

I didn’t originally come up with the idea of building a device to block telemarketers. I was belly-aching to a friend about them as I was teaching myself electronics and he suggested building something. Now there was an idea I could get behind. The idea for Scammer Jammer was born.

I started thinking about the idea and came up with a list of my “wants”:

  • The phone should ONLY ring when it is someone I know.
  • The handset should still receive caller ID properly. Even if it is someone I know, I want to decide if I really want to answer the phone.
  • People I don’t know or don’t want to talk to should go straight to an answering machine / Voice mail.
  • Telemarketers should just be hung up on.
  • There should be a centralized list of scammers, perhaps crowd sourced. When one user marks a caller as a scammer, then it is blocked for everyone.
  • The device needs to be remotely monitored. My parents don’t live in the same state but someday I might need to manage it for them.

At first, I was going to build a call blocker much like those I had seen but with more smarts – perhaps based on a raspberry Pi. I worked on that idea for several months. Various issues came up, most of which I can no longer even recall, and then I had a eureka moment!

The Scammer Jammer device should be as simple as possible – it would just take the caller ID from the phone, send it to a server, and the server would decide how to handle the call. That action would be returned to the Scammer Jammer and it could connect, answer, or block the call.

Sounded simple but it has been quite a learning experience to get this all to run. It took about a year to get the hardware fully designed.

Probably the most challenging part was generating my own caller Id signal. This not only achieves the goal of providing the handset with caller ID information, unlike other call blockers, but it allows me to transmit my own text to the handset. Thus, the user can assign names to phones that would otherwise be just ‘out of area’.

Once the hardware was done, I spent another 18 months on the software. I used sqlite as the database and produced a Raspberry Pi server capable of handling 30 simultaneous calls for a total of about 600 calls a minute during stress testing. The ‘production’ server I’m using is a linux Core-I7 computer. It should be capable of much higher calls rates, though I haven’t tested it.

Once the server was done I had not only achieved my initial goals but had went further – with a DB of 1.5M known telemarketers, Scammer Jammer can identify roughly 80% of telemarketers without any additional rules from the user. In fact, it has become so good, I no longer tell it to send unknown callers to the answering machine – almost everyone that calls is someone I probably should talk to, assuming I’m not grumpy.

It can even handle spoofing. Say your phone number is 123-555-1212. The telemarketers will call you with a phone number in the 123-555 exchange to fool you into thinking it is a local call so you answer. To get around this, I simply white-list the numbers in 123-555 that are allowed to ring my phone. I then create a 123-555 rule that forces everyone else to the answering machine.

Now the problem was only a Linux-knowledgeable person could use it because all of the rules were in flat files on a linux server. The last part of the puzzle was to write software that allowed the user to manage his rules and devices. This was written as a front-end/back-end.

Partially this client/server design is due to how sqlite works (there is no network access allowed to a sqlite db). There must be server software front-ending the sqlite db. Also, by designing it this way, I can have multiple front-ends.

The quickest front-end I could write is for windows, in Lazarus. This can be easily recompiled for Linux and MAC so the config software immediately became available for all 3 platforms. If/when I’m ready, I can address phones by either implementing the front-end in HTML or perhaps delphi for android.

My friends often ask why I designed Scammer Jammer for landlines / VoIP phones rather than cell phones. Fair question. My primary interest was to protect seniors and all of the ones I was thinking of have land lines. Further, my primary line is still a land line. Also, there are solutions already available for cell phones, though I haven’t used any so far.

Because the Scammer Jammer device uses a simple protocol to determine, from the server, how a call should be handled, there is no reason why software couldn’t be written for the phone that would take advantage of the back-end being used by the Scammer Jammer devices.

This device isn’t for everyone. It is just too expensive. I tried my best to keep costs down, but in its current form the parts are roughly $175. Price conscious consumers aren’t going to find this worth the cost. But it does start to make sense for people like me who DETEST telemarketers, seniors, small business owners that don’t have time to answer the phone for non-customers, etc.

The Scammer Jammer website can be seen here.

As I said at the beginning, I’m not sure where I’m going with Scammer Jammer yet. But it has done a great job at keeping me amused for over 2 years now!

Posted in c-electronics, c-lazarus, c-Misc, c-teensy | Tagged | 2 Comments

Create MAP file when Compiling for Teensy in Teensyduino

I needed to generate a compiler .MAP file for a project to examine my global variables. Sifting thru various somewhat vague explanations for generating a MAP file in the arduino IDE, I got it figured out.

In your Arduino/Teensyduino directory go to the directory:

hardware\teensy\avr\

and edit the file platform.txt

Find the lines :

## Link
recipe.c.combine.pattern=...

and between the parts

{build.flags.cpu}

and

-o "{build.path}/{build.project_name}.elf"

add

"-Wl,-Map,{build.path}/{build.project_name}.map"

for me the entire line looks like:

recipe.c.combine.pattern="{compiler.path}{build.toolchain}{build.command.gcc}" {build.flags.optimize} {build.flags.ld} {build.flags.ldspecs} {build.flags.cpu} "-Wl,-Map,{build.path}/{build.project_name}.map" -o "{build.path}/{build.project_name}.elf" {object_files} "{build.path}/{archive_file}" "-L{build.path}" {build.flags.libs}

Now when you compile, along with elf, hex files you will get map file:

Posted in c-teensy | Tagged | Leave a comment

Watch Dog Timer (WDT) for Teensy 3.1 and 3.2

I have had an ongoing Teensy project that is rather complex. Once in a great while (months), one of the units will hang somewhere in networking code. This is unacceptable and I’ve needed to implement a WDT, but I’ve been hesitant because I’ve not seen an obvious and simple example and I’ve been under the impression it is easy to brick a Teensy if the WDT is not implemented correctly.

After two network hangs in a matter of weeks, I decided I couldn’t put off WDT any longer.

This post is a summary of my research of implementing WDT with (I hope) simple example programs to show how to implement it yourself.

Resources

My primary resources have been:

This Teensy forum thread:

https://forum.pjrc.com/threads/25370-Teensy-3-0-Watchdog-Timer

and the microcontroller manual.

WDT Initialization Code

For WDT to be available, it has to be initialized within 256 clock cycles after boot. Most of the example code I’ve seen deals with implementing a hook called start_early_hook which is called withing the 256 clock cycles. WDT is then enabled in that hook.

I really don’t want WDT resetting the MCU while everything is first coming up. If there is a hang during the initialization phase, rebooting probably isn’t going to make things better, at least for my own code. I’d rather not start the WDT until initialization is complete.

After doing some research I found the ‘default’ start_early_hook found in llwuh.c and it sets up the WDT to be disabled BUT allow future modifications to the settings:

void startup_early_hook( ) __attribute__ ((weak));
void startup_early_hook( ) {
    WDOG_STCTRLH = WDOG_STCTRLH_ALLOWUPDATE;
 
    if ( PMC_REGSC & PMC_REGSC_ACKISO ) {
        llwuFlag = llwu_clear_flags( );// clear flags
        llwu_disable( );
    }
}

This default is exactly what I want – to be able to startup WDT at the end of my initialization phase!

Simple WDT Timeout and Program Reset

Program to Illustrate WDT Usage

This is about the simplest program I can come up with to illustrate how to implement the WDT. Comments afterwards…

// This sample program shows how to use the watch dog timer (WDT).

// When program starts, it turns LED off for 1 seconds.
// It then turns LED on, and pauses for 5 seconds letting you know it is ready to start.
// WDT is initialized, and loop starts. It will flash led and reset wdt for the first 10 secs.
// After that, it stops resetting wdt. This causes the WDT to reboot and the cycle starts over.

const int           led                 = 13;

bool                ledState            = false;
unsigned long       timer;

void setup() {

    // initialize the digital pin as an output.
    pinMode(led, OUTPUT);

    // Indicate we are starting over by hold led off for 1s
    ledState = false;
    digitalWrite(led, ledState);
    delay(1000UL);

    // Indicate we are in setup by hold LED on
    ledState = true;
    digitalWrite(led, ledState);
    delay(5000UL);

    // Setup WDT
    noInterrupts();                                         // don't allow interrupts while setting up WDOG
    WDOG_UNLOCK = WDOG_UNLOCK_SEQ1;                         // unlock access to WDOG registers
    WDOG_UNLOCK = WDOG_UNLOCK_SEQ2;
    delayMicroseconds(1);                                   // Need to wait a bit..

    // for this demo, we will use 1 second WDT timeout (e.g. you must reset it in < 1 sec or a boot occurs)
    WDOG_TOVALH = 0x006d;
    WDOG_TOVALL = 0xdd00;

    // This sets prescale clock so that the watchdog timer ticks at 7.2MHz
    WDOG_PRESC  = 0x400;

    // Set options to enable WDT. You must always do this as a SINGLE write to WDOG_CTRLH
    WDOG_STCTRLH |= WDOG_STCTRLH_ALLOWUPDATE |
        WDOG_STCTRLH_WDOGEN | WDOG_STCTRLH_WAITEN |
        WDOG_STCTRLH_STOPEN | WDOG_STCTRLH_CLKSRC;
    interrupts();

}

void loop() {

timer = millis() + 10000UL;                                 // length of time we will reset WDT

while (true) {
    ledState = !ledState;
    digitalWrite(led, ledState);
    delay(100UL);
    if (millis() < timer) {                                 // Have we timed out yet?
        noInterrupts();                                     //   No - reset WDT
        WDOG_REFRESH = 0xA602;
        WDOG_REFRESH = 0xB480;
        interrupts();
        }
    } // while
}

Commentary

The idea behind this program is to setup WDT with a 1 second timeout, start flashing an LED, then after 10 seconds stop resetting WDT so it causes a reboot. You just watch the LED to verify the program works.

To setup WDT, disable interrupts, then write a 2 byte sequence to the WDOG_UNLOCK register. Once you write this sequence, you have 256 clock cycle to complete all WDT settings, so don’t do anything else except WDT setup.

Next I indicate how long I want the WDT timer to run, 1 second in this case. That means I must reset (e.g. kick or pat) the watch dog in < 1 sec or a reboot occurs.

I did a lot of messing around and found that if the prescaler (WDOG_PRESC) is set to 0x400, then the WDT timer runs at about 7.2MHz. (Using a prescaler of 0 gives a clock rate of 36MHz). Note that these values are for my Teensy’s clock of 72MHz. If you over clock, I would assume these values change.

So if I want a 1 second timeout, I would use 7,200,000 which is 0x006DDD00 which is what you see I assign to the WDOG_TOVALH and WDOG_TOVALL registers.

Finally I enable the WDT AND allow future modifications. You are only allowed 1 write to this register after you unlock it, so you must do a single assignment.

Don’t forget to turn interrupts back on.

The program should then be fairly self-explanatory down to the point where I reset the WDT.

To do the reset you are going to write a byte sequence to the WDOG_REFRESH register. This, too, must be done with interrupts off.

Now that I have it up and running, the Teensy WDT is just as easy as the Arduino’s!

Passing Information into the Program after a WDT Reset

Reset Reason

While researching WDT for the Teensy, I found one of “Duff’s” posts in the forum post mentioned in the resources to be quite interesting. He examines the RCM_SRS0 and RCM_SRS1 registers to display why the MCU was reset. I tested those that I could and here is a summary:

RCM_SRS1 & RCM_SRS1_SACKERR   Stop Mode Acknowledge Error Reset
RCM_SRS1 & RCM_SRS1_MDM_AP    MDM-AP Reset
RCM_SRS1 & RCM_SRS1_SW        Software Reset			True when reboot with SCB_AIRCR = 0x05FA0004
RCM_SRS1 & RCM_SRS1_LOCKUP    Core Lockup Event Reset
RCM_SRS0 & RCM_SRS0_POR       Power-on Reset			True when power removed/reapplied
RCM_SRS0 & RCM_SRS0_PIN       External Pin Reset		True when reboot due to software download
RCM_SRS0 & RCM_SRS0_WDOG      Watchdog(COP) Reset		True when WDT reboots MCU
RCM_SRS0 & RCM_SRS0_LOC       Loss of External Clock Reset
RCM_SRS0 & RCM_SRS0_LOL       Loss of Lock in PLL Reset
RCM_SRS0 & RCM_SRS0_LVD       Low-voltage Detect Reset		Also true when power removed/reapplied

Global DMAMEM Variables

It would be nice to know where I was in the code when the WDT occurred. When the WDT occurs, your program is re-initialized for the most part.

In the program I’m developing this for, I actually maintain a queue of the last <n> events the program processed. For argument’s sake,Ā  let’s say I would like to save the last event so it is available to the program when it restarts.

It turns out that if you declare a variable DMAMEM (e.g. DMAMEM int), that variable will NOT be re-initialized when WDT occurs. This allows you to detect and

Here is the example program:

// This sample program shows how to use the watch dog timer (WDT).

// To use, download and start Teensy. LED will turn solid red meaning
// connect to Teensy with terminal.

// Once connected, some information will be printed. After done, you
// will be asked to disconnect to proceed with test.

// Once you disconnect, the LED will flash fast until WDT reboots the
// Teensy at which time the LED is on solid again, awaiting the terminal
// to be connected.

#include            <Arduino.h>
#include            <kinetis.h>                              // contains WDOG constants

const int           led                 = 13;

DMAMEM unsigned int dmaTest;
DMAMEM unsigned int dmaTestInit;
bool                ledState            = false;
unsigned long       timeOut             = 0UL;
unsigned long       timer               = 1000UL;

void setup() {

    pinMode(led, OUTPUT);                                   // initialize the digital pin as an output.

    ledState = true;                                        // while waiting for terminal to connect, hold LED on
    digitalWrite(led, ledState);

    while (!Serial.dtr()) {                                 // wait for terminal to connect
        }

    // notify user we are connected and running
    ledState = false;
    digitalWrite(led, ledState);
    Serial.println("Terminal Connected.");

    // Display reason the Teensy was last reset
    Serial.println();
    Serial.println("Reason for last Reset: ");

    if (RCM_SRS1 & RCM_SRS1_SACKERR)   Serial.println("Stop Mode Acknowledge Error Reset");
    if (RCM_SRS1 & RCM_SRS1_MDM_AP)    Serial.println("MDM-AP Reset");
    if (RCM_SRS1 & RCM_SRS1_SW)        Serial.println("Software Reset");                   // reboot with SCB_AIRCR = 0x05FA0004
    if (RCM_SRS1 & RCM_SRS1_LOCKUP)    Serial.println("Core Lockup Event Reset");
    if (RCM_SRS0 & RCM_SRS0_POR)       Serial.println("Power-on Reset");                   // removed / applied power
    if (RCM_SRS0 & RCM_SRS0_PIN)       Serial.println("External Pin Reset");               // Reboot with software download
    if (RCM_SRS0 & RCM_SRS0_WDOG)      Serial.println("Watchdog(COP) Reset");              // WDT timed out
    if (RCM_SRS0 & RCM_SRS0_LOC)       Serial.println("Loss of External Clock Reset");
    if (RCM_SRS0 & RCM_SRS0_LOL)       Serial.println("Loss of Lock in PLL Reset");
    if (RCM_SRS0 & RCM_SRS0_LVD)       Serial.println("Low-voltage Detect Reset");
    Serial.println();

    if (dmaTestInit != 0xaaaa) {
        // on first time run, dmaTestInit contains random data, not the 0xAAA(1010101010...)
        // we seek. When dmaTestInit is garbage, we give a warning and set it.
        Serial.println("dmaTest value is invalid.");
        dmaTestInit = 0xaaaa;
        }
    else {
        // If dmaTestInit is correct, dmaTest has a good value
        Serial.printf("Current dmaTest Value: %u\n\r", dmaTest);
        }

    // give dmaTest a random "good" value and let user know what it will be
    randomSeed(analogRead(0));
    dmaTest = random(0, 32768);
    Serial.printf("Next dmaTest Value: %u.\n\r", dmaTest);
    Serial.println();

    // You cannot allow Teensy to reboot with USB connected, to tell user to disconnect terminal.
    Serial.println("Disconnect terminal to proceed with WDT test!");
    while (Serial.dtr()) {}

    ledState = !ledState;                                   // init LED
    digitalWrite(led, ledState);

    // enable WDT
    noInterrupts();                                         // don't allow interrupts while setting up WDOG
    WDOG_UNLOCK = WDOG_UNLOCK_SEQ1;                         // unlock access to WDOG registers
    WDOG_UNLOCK = WDOG_UNLOCK_SEQ2;
    delayMicroseconds(1);                                   // Need to wait a bit..

    WDOG_TOVALH = 0x006d;                                   // 1 second WDT
    WDOG_TOVALL = 0xdd00;
    WDOG_PRESC  = 0x400;
    WDOG_STCTRLH |= WDOG_STCTRLH_ALLOWUPDATE |
        WDOG_STCTRLH_WDOGEN | WDOG_STCTRLH_WAITEN |
        WDOG_STCTRLH_STOPEN | WDOG_STCTRLH_CLKSRC;
    interrupts();
}

void loop() {

timer = millis() + 10000UL;                                 // length of time we will reset WDT

while (true) {
    ledState = !ledState;
    digitalWrite(led, ledState);
    delay(100UL);
    if (millis() < timer) {                                 // Have we timed out yet?
        noInterrupts();                                     //   No - reset WDT
        WDOG_REFRESH = 0xA602;
        WDOG_REFRESH = 0xB480;
        interrupts();
        }
    } // while
}

Commentary

I used the prior example as the base program, so the actual setup and usage of the WDT is the same.

All of the new code is in the setup function. First, the reason for the last reset is displayed using the RCM_SRC1 and RCM_SRS1 registers.

Next, we look to see if dmaTestInit has a valid value. If not, we can assume dmaTest is not properly set.

Regardless, we then set dmaTestInit to a known value and dmaTest value to some random integer which we tell the user so he can re-check the value of dmaTest on the next WDT reset.

Triggering WDOG Interrupt

In the prior example, I experimented with writing a value to RAM not EEPROM. Why? 2 reasons. First, writing to EEPROM is way slower, which may or may not be an issue depending on how fast my events occur. Second, there are a fixed number of EEPROM writes allowed, about 100,000 (https://www.pjrc.com/teensy/td_libs_EEPROM.html). So I don’t want to go crazy writing to EEPROM.

HOWEVER, it would be really nice to write the LAST event to EEPROM when a WDT reset occurs.

With the Arduino and ATTiny MCUs I’ve used, there has been no graceful way to handle the WDT reset (at least as far a I know). The WDT reset is the same as if the user simply reset power.

This example explores setting up an ISR to be called when the WDT resets. I won’t write EEPROM in this example – I just want to verify I could for when I implement this code into the production project.

Example Program

Here is the example program. It is very close to the prior program with just a few additions:

// This sample program shows how to use the watch dog timer (WDT).

// To use, download and start Teensy. LED will turn solid red meaning
// connect to Teensy with terminal.

// Once connected, some information will be printed. After done, you
// will be asked to disconnect to proceed with test.

// Once you disconnect, the LED will flash fast until WDT reboots the
// Teensy at which time the LED is on solid again, awaiting the terminal
// to be connected.

#include            <Arduino.h>
#include            <kinetis.h>                              // contains WDOG constants

const int           led                 = 13;

DMAMEM unsigned int dmaTest;
DMAMEM unsigned int dmaTestInit;
bool                ledState            = false;
unsigned long       timeOut             = 0UL;
unsigned long       timer               = 1000UL;

// This routine MUST be named watchdog_isr. It will be called
// when the WDT pops and the reset is intiated.

// This function must complete in < time than the WDT would take.
// In this example, I'm using a WDT timeout of 1s, so it must be done
// in < 1 second.

void watchdog_isr() {

// set dmaTest to 777, letting me know this function was called
dmaTest = 777;

}

void setup() {

    pinMode(led, OUTPUT);                                   // initialize the digital pin as an output.

    ledState = true;                                        // while waiting for terminal to connect, hold LED on
    digitalWrite(led, ledState);

    while (!Serial.dtr()) {                                 // wait for terminal to connect
        }

    // notify user we are connected and running
    ledState = false;
    digitalWrite(led, ledState);
    Serial.println("Terminal Connected.");

    // Display reason the Teensy was last reset
    Serial.println();
    Serial.println("Reason for last Reset: ");

    if (RCM_SRS1 & RCM_SRS1_SACKERR)   Serial.println("Stop Mode Acknowledge Error Reset");
    if (RCM_SRS1 & RCM_SRS1_MDM_AP)    Serial.println("MDM-AP Reset");
    if (RCM_SRS1 & RCM_SRS1_SW)        Serial.println("Software Reset");                   // reboot with SCB_AIRCR = 0x05FA0004
    if (RCM_SRS1 & RCM_SRS1_LOCKUP)    Serial.println("Core Lockup Event Reset");
    if (RCM_SRS0 & RCM_SRS0_POR)       Serial.println("Power-on Reset");                   // removed / applied power
    if (RCM_SRS0 & RCM_SRS0_PIN)       Serial.println("External Pin Reset");               // Reboot with software download
    if (RCM_SRS0 & RCM_SRS0_WDOG)      Serial.println("Watchdog(COP) Reset");              // WDT timed out
    if (RCM_SRS0 & RCM_SRS0_LOC)       Serial.println("Loss of External Clock Reset");
    if (RCM_SRS0 & RCM_SRS0_LOL)       Serial.println("Loss of Lock in PLL Reset");
    if (RCM_SRS0 & RCM_SRS0_LVD)       Serial.println("Low-voltage Detect Reset");
    Serial.println();


    if (dmaTestInit != 0xaaaa) {
        // on first time run, dmaTestInit contains random data, not the 0xAAA(1010101010...)
        // we seek. When dmaTestInit is garbage, we give a warning and set it.
        Serial.println("dmaTest value is invalid.");
        dmaTestInit = 0xaaaa;
        }
    else {
        // If dmaTestInit is correct, dmaTest has a good value
        Serial.printf("Current dmaTest Value: %u\n\r", dmaTest);
        }

    // give dmaTest a random "good" value and let user know what it will be
    randomSeed(analogRead(0));
    dmaTest = random(0, 32768);
    Serial.printf("Next dmaTest Value: %u.\n\r", dmaTest);
    Serial.println();

    // You cannot allow Teensy to reboot with USB connected, to tell user to disconnect terminal.
    Serial.println("Disconnect terminal to proceed with WDT test!");
    while (Serial.dtr()) {}

    ledState = !ledState;                                   // init LED
    digitalWrite(led, ledState);

    // enable WDT
    noInterrupts();                                         // don't allow interrupts while setting up WDOG
    WDOG_UNLOCK = WDOG_UNLOCK_SEQ1;                         // unlock access to WDOG registers
    WDOG_UNLOCK = WDOG_UNLOCK_SEQ2;
    delayMicroseconds(1);                                   // Need to wait a bit..

    WDOG_TOVALH = 0x006d;                                   // 1 second WDT
    WDOG_TOVALL = 0xdd00;
    WDOG_PRESC  = 0x400;
    WDOG_STCTRLH |= WDOG_STCTRLH_ALLOWUPDATE |
        WDOG_STCTRLH_WDOGEN | WDOG_STCTRLH_WAITEN |
        WDOG_STCTRLH_STOPEN | WDOG_STCTRLH_CLKSRC |
        WDOG_STCTRLH_IRQRSTEN;                              // Tell WDOG to trigger the interrupt
    interrupts();

    NVIC_ENABLE_IRQ(IRQ_WDOG);                              // enable the call to the watchdog_isr function

}

void loop() {

timer = millis() + 10000UL;                                 // length of time we will reset WDT

while (true) {
    ledState = !ledState;
    digitalWrite(led, ledState);
    delay(100UL);
    if (millis() < timer) {                                 // Have we timed out yet?
        noInterrupts();                                     //   No - reset WDT
        WDOG_REFRESH = 0xA602;
        WDOG_REFRESH = 0xB480;
        interrupts();
        }
    } // while

}

Commentary

To enable the IRQ, you must set the WDOG control register to transmit the WDOG interrupt. You must also call NVIC_ENABLE_IRQ to have the MCU process the interrupt and call the watchdog_isr service routing.

Once that is done, it is just a matter of putting the necessary code in the watchdog_isr.

In this example, I simply overwrite the value of dmaTest in the ISR so I can verify it was called.

This makes it evident the ISR was called. Here is example of the output:

Terminal Connected.

Reason for last Reset: 
Power-on Reset
Low-voltage Detect Reset

dmaTest value is invalid.
Next dmaTest Value: 1298.

Disconnect terminal to proceed with WDT test!


<Your 'COM30' connection has terminated>

Terminal Connected.

Reason for last Reset: 
Watchdog(COP) Reset

Current dmaTest Value: 777
Next dmaTest Value: 6826.

Disconnect terminal to proceed with WDT test!

The first time connecting to the Teensy, dmaTest is uninitialized and set to 1298.

The WDT resets, calls the ISR, and dmaTest is now set to 777. This is seen when reconnecting to the Teensy.

Conclusion

Implementing the Teensy watchdog timer is nearly as straight-forward as it is for the Arduino or ATTiny 85.

Unlike the Arduino the Teensy can to communicate a WDT reset and pass status via DMAMEM variable (actually maybe Arduino can do this as well and I just have never seen it).

Finally, being able to hook the WDT reset so code can be executed before hand will end up being very useful for my intended project.

As long as you use the default ‘start_early_hook’, it should be about impossible to brick the Teensy. Since it starts up with WDT disabled, loops interrupted by the WDT should not have a chance before you can force a software update.

Update

I implemented the WDT into my production code and found that the eeprom library I’m using isn’t working with the watchdog_isr. I used DMAMEM to pass what I needed to the newly started code and haven’t research the eeprom problem any further.

Nov 2017 Update

To disable WDT, use this code:

NVIC_DISABLE_IRQ(IRQ_WDOG);

noInterrupts(); // don't allow interrupts while setting up WDOG
 WDOG_UNLOCK = WDOG_UNLOCK_SEQ1; // unlock access to WDOG registers
 WDOG_UNLOCK = WDOG_UNLOCK_SEQ2;
 delayMicroseconds(1); // Need to wait a bit..

// Set options to enable WDT. You must always do this as a SINGLE write to WDOG_CTRLH
 WDOG_STCTRLH = WDOG_STCTRLH_ALLOWUPDATE;

interrupts();

 

Posted in c-teensy, Uncategorized | Tagged , | 1 Comment

Using tcpdump with DD-WRT

I’ve been having a weird networking issue. I’m having trouble determining if it is Comcast’s issue or mine. I see the packets in question leave the remote client, but they never come out the inside ethernet port of my comcast router. I assume the problem is comcast’s but I need to really be sure. I need to monitor the outside interface of my comcast router.

I have a Buffalo router connected to a cable modem (comcast doesn’t supply any of my equipment because I want full control). The Buffalo router comes with dd-wrt pre-installed.

At first I was going to connect a hub between the router and modem so I could tap into the outside interface using wireshark (see Sniffing *ALL* Arduino Network Packets). The problem with tapping into the connection like that is the hub is a 10M device and I really don’t want to downgrade my service like that.

Then it occurred to me I might be able to use tcpdump on the router since it is really just a small unix device. I did a quick check and sure enough, Buffalo was kind enough to include tcpdump in the operating system.

I checked further and found my other (Rosewill) routers do NOT have tcpdump installed. To proceed, you may need to install tcpdump onto your router. If so, google something like ‘How to install tcpdump on dd-wrt’. Here is one such article: https://www.pentest.ro/installing-tcpdump-on-dd-wrt/ .

Enable USB

Unless you just want to watch the raw tcpdump, which is about as exciting as watching grass grow, you are going to want to redirect tcpdump’s output to a file and then examine the output file with wireshark.

On the Buffalo router, this is pretty easy. In Services | USB, just enable USB storage support:

When you insert a USB thumb drive you should see it mount and the path will also be displayed:

--- /dev/sda1
Block device, size 14.83 GiB (15927345152 bytes)
FAT32 file system (hints score 4 of 5)
Volume size 14.83 GiB (15923150848 bytes, 485936 clusters of 32 KiB)
/dev/sda1 mounted to /tmp/mnt/sda1

Determine the Proper tcpdump Command

With storage now available, next determine the tcpdump command you wish to use and test it.

telnet or ssh into your router and login as root (password is the same as the one you use for HTML login).Ā  You’ll see something like:

login as: root
DD-WRT v3.0-r30355 std (c) 2016 NewMedia-NET GmbH
Release: 09/13/16
root@rtr's password:
<< GRAPHIC OMITTED >>
BusyBox v1.24.2 (2016-09-13 15:32:42 CEST) built-in shell (ash)

root@rtr:~#

I want to capture all traffic for tcp port 22 on the outside interface so try a tcpdump such as:

tcpdump -s 0 -i eth1 port 22

Generate some test traffic. If this works, then verify you can output to the USB drive:

tcpdump -s 0 -i eth1 -w /tmp/mnt/sda1/out.pcap port 22

Run tcpdump in the Background

Once you are satisfied with your tcpdump, the next step is to run that in the background so you don’t need to keep a telnet / ssh session open.

In dd-wrt, go to Admin | Command and enter the command WITH ‘&’ at the end:

Now click on Run Commands and the tcpdump will start running in the background.

Stopping tcpdump

The tcpdump is now going to run until you reboot the router or you kill the tcpdump process.

To kill the process use

ps | grep tcpdump

to find the process id (PID) of the tcpdump process. Then use

kill PID

replacing PID with the proper process id # and it will kill tcpdump.

 

Posted in c-Misc | Tagged | Leave a comment

Compiling Free Pascal / Lazarus on Orange Pi

I had no issues following my instructions, Compiling the Latest Lazarus/Free Pascal for Raspberry Pi. This was, as usual, not a short process. It takes an hour, easy, assuming no mistakes are made.

I also noticed that the compiler hits the CPU so hard that I still lost a CPU core to overheating. That’s a little disappointing.

Unless you really need the most recent version of Lazarus, just use

apt-get install lazarus

The compiler was installed and a simple program tested.

In doing this, I was reminded why I don’t run Pascal on normal RPIs. It is too slow – there is too much IO on the SD card. I have a special RPI with a USB based hard drive for that very purpose.

I have moved Lazarus programs compiled on the RPI to the OPI and they work fine.

I expect that will conclude my testing with the Orange Pi One. I have now ordered an Orange Pi PC which has a faster CPU and more IO options to experiment with.

Posted in c-opi | 4 Comments

Orange Pi and Teensy Loader Work Together

I have installed RPI Linux Installer of Teensyduino on an RPI previously.

I simply took the teensy loader code and copied it from the RPI to the OPI, and tested it.

The testing was not extensive, but the software did run, so I expect I will be able to use the teensy loader to upgrade Teensies in the field with an OPI if necessary.

Posted in c-opi | Leave a comment

Orange Pi Setup / Use Issues

I followed my own ‘setup’ procedure with my new OPI. This includes building standard users, installing software I always use (FTP, SMTP, etc), and so on.

This gave me a chance to see what kind of issues I might have running Raspbian on OPI.

For the most part, I only saw a few problems. Unfortunately, they have all been somewhat nasty problems that took some time to resolve.

That being said, most everything works. As I was doing research, users were complaining bitterly about how unstable / unusable Raspian on OPI is. So far my opinion is nowhere near as negative. BUT I will also say this implementation of Raspian obviously doesn’t have the same kind of attention to detail that one would find on Raspberry Pi.

Here are the issues I have seen:

HDMI to DVI Converter

As mentioned in Orange PI OneĀ Installation, you really shouldn’t plan on using a DVI monitor. You might get it to work, you might not.

raspi-config Can’t Expand the File System

Everything I normally use raspi-config for (keyboard config, timezone, enable SSH) works EXCEPT it can’t expand the file system.

I did this by sticking the SD card into another system running linux and used gparted to resize the partition.

Can’t Use New Users

This was almost a show stopper: after creating my ‘standard’ users, I found I could not log into them. Well, I could login, but they would immediately exit / logoff.

This one took a few hours to track down. Not the kind of bug you would think would make it past QA. It’s been around a while and evidently it still isn’t fixed in the distribution.

This is corrected by tweaking the running configuration with:

echo "vm.mmap_min_addr = 4096" > /etc/sysctl.d/mmap_min_addr.conf

mmap_miin_addr.conf which will be executed each time the system is started.

VNC Install

This is more a warning than an error.

After installing VNC and trying to run tightvncserver for the first time I got an error regarding missing .Xauthority file and the server didn’t work correctly.

I restarted the service. This time there was no error, and it did work. Yay!

CPU(s) Shut Down Due to Heat

While trolling syslog, I discovered constant error messages regarding “CPU Budget: Temperature”.

I started looking around and others were complaining about this and about their CPU(s) being shutdown due to excessive heat.

Looking close in my log, sure enough, I found my CPU3 was being shutdown as well:

Sep 5 15:43:30 opi kernel: [ 4.920061] CPU Budget: Temperature: 73 Limit state:1 item[1200000,3,-1,0 0]
Sep 5 15:43:30 opi kernel: [ 4.920072] CPU Budget:Try to down cpu 3, cluster0 online 4, limit 3
Sep 5 15:43:30 opi kernel: [ 4.956805] CPU3: shutdown
Sep 5 15:43:30 opi kernel: [ 4.963550] [hotplug]: cpu(0) try to kill cpu(3)
Sep 5 15:43:30 opi kernel: [ 4.972376] [hotplug]: cpu3 is killed! .

Running top and using option ‘1’, sure enough, I only had 3 CPUs running.

I started researching this problem and found people talking about changing frequency, etc, etc. I was wary about making such changes. They also said you should be using a heatsink.

Well, I am using a heat sink so I checked the case and it seemed pretty warm to me.

I removed the OPI from the case and restarted it. So far no error messages in syslog.

This problem isn’t actually the fault of the OPI, but the case mfg whom didn’t do an adequate job of ventilation.

Sep 11, 2017 Update

I was given a copy of armbian to play with. It was much better setup to handle the Orange Pi, but the copy I had still had some issues, so I went over to Ambian and downloaded the latest version of Ubunutu Desktop for Armbian at https://www.armbian.com/download/ .

This is much slicker than Raspian. I’d recommend it over Raspian for the most part. I’m not going to use it, at least for now, mainly because I have a ton of RPI’s running on Raspian right now and I want to keep everything consistent.

One big benefit of Armbian is it doesn’t experience the CPU shutdown issue due to over heating.

After pondering that difference, I decided the hardware is the hardware, there must be a difference in how Armbian is configured vs. Raspian.

I ended up copying bits and pieces of /boot/script.fex (aka script.bin) from Armbian to Raspian. Essentially, I now allow the CPU to get a little hotter, plus I think I am allowing the CPU frequency to drop either quicker or further (or maybe both).

Enclosed is the script.fex I’m using that no longer has the CPU shutdown issue. You will need to convert this to script.bin using the fex2bin tool.

USE AT YOUR OWN RISK. I just copied and pasted values I thought might help. There may be some weird side effect that causes the CPU to burst into flames. I don’t know – these changes are way outside the scope of my Linux knowledge!

[product]
version = "100"
machine = "Xunlong Orange Pi One"

[platform]
debug_mode = 1
eraseflag = 1
next_work = 2

[target]
boot_clock = 1008
storage_type = -1

[key_detect_en]
keyen_flag = 0

[fel_key]
fel_key_max = 7
fel_key_min = 2

[card_boot]
logical_start = 40960
sprite_work_delay = 500
sprite_err_delay = 200
sprite_gpio0 = port:PL10<1><default><default><default>
next_work = 3

[box_start_os]
used = 1
start_type = 1
irkey_used = 1
pmukey_used = 1
pmukey_num = 3
led_power = 0
led_state = 0

[boot_init_gpio]
used = 1
gpio0 = port:PL10<1><default><default><1>
gpio1 = port:PG11<1><default><default><1>

[recovery_para]
used = 1
mode = 2
recovery_key = port:PL04<0><default><default><default>

[pm_para]
standby_mode = 1

[card0_boot_para]
card_ctrl = 0
card_high_speed = 1
card_line = 4
sdc_d1 = port:PF00<2><1><2><default>
sdc_d0 = port:PF01<2><1><2><default>
sdc_clk = port:PF02<2><1><2><default>
sdc_cmd = port:PF03<2><1><2><default>
sdc_d3 = port:PF04<2><1><2><default>
sdc_d2 = port:PF05<2><1><2><default>

[card2_boot_para]
card_ctrl = 2
card_high_speed = 1
card_line = 8
sdc_cmd = port:PC06<3><1><2><default>
sdc_clk = port:PC05<3><1><2><default>
sdc_d0 = port:PC08<3><1><2><default>
sdc_d1 = port:PC09<3><1><2><default>
sdc_d2 = port:PC10<3><1><2><default>
sdc_d3 = port:PC11<3><1><2><default>
sdc_d4 = port:PC12<3><1><2><default>
sdc_d5 = port:PC13<3><1><2><default>
sdc_d6 = port:PC14<3><1><2><default>
sdc_d7 = port:PC15<3><1><2><default>
sdc_2xmode = 1
sdc_ddrmode = 1

[twi_para]
twi_port = 0
twi_scl = port:PA11<2><default><default><default>
twi_sda = port:PA12<2><default><default><default>

[uart_para]
uart_debug_port = 0
uart_debug_tx = port:PA04<2><1><default><default>
uart_debug_rx = port:PA05<2><1><default><default>

[force_uart_para]
force_uart_port = 0
force_uart_tx = port:PF02<3><1><default><default>
force_uart_rx = port:PF04<3><1><default><default>

[jtag_para]
jtag_enable = 0
jtag_ms = port:PA00<3><default><default><default>
jtag_ck = port:PA01<3><default><default><default>
jtag_do = port:PA02<3><default><default><default>
jtag_di = port:PA03<3><default><default><default>

[clock]
pll_video = 297
pll_ve = 402
pll_periph0 = 600
pll_gpu = 576
pll_periph1 = 600
pll_de = 864

[dram_para]
dram_clk = 624
dram_type = 3
dram_zq = 0x3b3bfb
dram_odt_en = 1
dram_para1 = 283377664
dram_para2 = 0
dram_mr0 = 6208
dram_mr1 = 64
dram_mr2 = 24
dram_mr3 = 2
dram_tpr0 = 0x48a192
dram_tpr1 = 0x1c2418d
dram_tpr2 = 0x76051
dram_tpr3 = 0x0
dram_tpr4 = 0x0
dram_tpr5 = 0x0
dram_tpr6 = 0x64
dram_tpr7 = 0x0
dram_tpr8 = 0x0
dram_tpr9 = 0x0
dram_tpr10 = 0x0
dram_tpr11 = 0x6aaa0000
dram_tpr12 = 0x7979
dram_tpr13 = 0x800800

[wakeup_src_para]
cpu_en = 0
cpu_freq = 48
pll_ratio = 273
dram_selfresh_en = 1
dram_freq = 36
wakeup_src0 =
wakeup_src_wl = port:PG10<4><default><default><0>
wakeup_src_bt = port:PL03<6><default><default><0>

[twi0]
twi_used = 1
twi_scl = port:PA11<2><default><default><default>
twi_sda = port:PA12<2><default><default><default>

[twi1]
twi_used = 1
twi_scl = port:PA18<3><default><default><default>
twi_sda = port:PA19<3><default><default><default>

[twi2]
twi_used = 0
twi_scl = port:PE12<3><default><default><default>
twi_sda = port:PE13<3><default><default><default>

[uart0]
uart_used = 1
uart_port = 0
uart_type = 2
uart_tx = port:PA04<2><1><default><default>
uart_rx = port:PA05<2><1><default><default>

[uart1]
uart_used = 0
uart_port = 1
uart_type = 4
uart_tx = port:PG06<2><1><default><default>
uart_rx = port:PG07<2><1><default><default>
uart_rts = port:PG08<2><1><default><default>
uart_cts = port:PG09<2><1><default><default>

[uart2]
uart_used = 0
uart_port = 2
uart_type = 4
uart_tx = port:PA00<2><1><default><default>
uart_rx = port:PA01<2><1><default><default>
uart_rts = port:PA02<2><1><default><default>
uart_cts = port:PA03<2><1><default><default>

[uart3]
uart_used = 0
uart_port = 3
uart_type = 4
uart_tx = port:PA13<3><1><default><default>
uart_rx = port:PA14<3><1><default><default>
uart_rts = port:PA15<3><1><default><default>
uart_cts = port:PA16<3><1><default><default>

[spi0]
spi_used = 1
spi_cs_bitmap = 1
spi_mosi = port:PC00<3><default><default><default>
spi_miso = port:PC01<3><default><default><default>
spi_sclk = port:PC02<3><default><default><default>
spi_cs0 = port:PC03<3><1><default><default>

[spi1]
spi_used = 0
spi_cs_bitmap = 1
spi_cs0 = port:PA13<2><1><default><default>
spi_sclk = port:PA14<2><default><default><default>
spi_mosi = port:PA15<2><default><default><default>
spi_miso = port:PA16<2><default><default><default>

[spi_devices]
spi_dev_num = 1

[spi_board0]
modalias = "spidev"
max_speed_hz = 33000000
bus_num = 0
chip_select = 0
mode = 0
full_duplex = 1
manual_cs = 0

[gpio_para]
gpio_used = 0
gpio_num = 0

[leds_para]
leds_used = 1
green_led = port:PL10<1><default><default><1>
green_led_active_low = 0
red_led = port:PA15<1><default><default><0>
red_led_active_low = 0

[ths_para]
ths_used = 1
ths_trip1_count = 6
ths_trip1_0 = 75
ths_trip1_1 = 80
ths_trip1_2 = 85
ths_trip1_3 = 90
ths_trip1_4 = 95
ths_trip1_5 = 105
ths_trip1_6 = 0
ths_trip1_7 = 0
ths_trip1_0_min = 0
ths_trip1_0_max = 1
ths_trip1_1_min = 1
ths_trip1_1_max = 2
ths_trip1_2_min = 2
ths_trip1_2_max = 3
ths_trip1_3_min = 3
ths_trip1_3_max = 4
ths_trip1_4_min = 4
ths_trip1_4_max = 5
ths_trip1_5_min = 5
ths_trip1_5_max = 7
ths_trip1_6_min = 0
ths_trip1_6_max = 0
ths_trip2_count = 1
ths_trip2_0 = 105

[cooler_table]
cooler_count = 8
cooler0 = "1200000 4 4294967295 0"
cooler1 = "912000 4 4294967295 0"
cooler2 = "768000 4 4294967295 0"
cooler3 = "648000 4 4294967295 0"
cooler4 = "480000 4 4294967295 0"
cooler5 = "480000 3 4294967295 0"
cooler6 = "480000 2 4294967295 0"
cooler7 = "480000 1 4294967295 0"

[nand0_para]
nand_support_2ch = 0
nand0_used = 0
nand0_we = port:PC00<2><default><default><default>
nand0_ale = port:PC01<2><default><default><default>
nand0_cle = port:PC02<2><default><default><default>
nand0_ce1 = port:PC03<2><default><default><default>
nand0_ce0 = port:PC04<2><default><default><default>
nand0_nre = port:PC05<2><default><default><default>
nand0_rb0 = port:PC06<2><default><default><default>
nand0_rb1 = port:PC07<2><default><default><default>
nand0_d0 = port:PC08<2><default><default><default>
nand0_d1 = port:PC09<2><default><default><default>
nand0_d2 = port:PC10<2><default><default><default>
nand0_d3 = port:PC11<2><default><default><default>
nand0_d4 = port:PC12<2><default><default><default>
nand0_d5 = port:PC13<2><default><default><default>
nand0_d6 = port:PC14<2><default><default><default>
nand0_d7 = port:PC15<2><default><default><default>
nand0_ndqs = port:PC16<2><default><default><default>

[boot_disp]
advert_disp = 0
auto_hpd = 1
output_type = 4
hdmi_channel = 0
hdmi_mode = 4
cvbs_channel = 1
cvbs_mode = 11
output_full = 1
hdmi_mode_check = 1

[disp_init]
disp_init_enable = 1
disp_mode = 0
screen0_output_type = 3
screen0_output_mode = 10
screen1_output_type = 3
screen1_output_mode = 10
fb0_format = 0
fb0_width = 0
fb0_height = 0
fb1_format = 0
fb1_width = 0
fb1_height = 0
hdcp_enable = 0
hdmi_cts_compatibility = 1

[hdmi_para]
hdmi_used = 1
hdmi_power = "vcc-hdmi-18"
hdcp_enable = 0
hdmi_cts_compatibility = 1

[tv_para]
tv_used = 0
tv_dac_used = 1
tv_dac_src0 = 0

[pwm0_para]
pwm_used = 0
pwm_positive = port:PA05<3><0><default><default>

[gmac0]
gmac_used = 2
gmac_power1 =

[csi0]
vip_used = 1
vip_mode = 0
vip_dev_qty = 1
vip_define_sensor_list = 0
vip_csi_pck = port:PE00<2><default><default><default>
vip_csi_mck = port:PE01<2><default><default><default>
vip_csi_hsync = port:PE02<2><default><default><default>
vip_csi_vsync = port:PE03<2><default><default><default>
vip_csi_d0 = port:PE04<2><default><default><default>
vip_csi_d1 = port:PE05<2><default><default><default>
vip_csi_d2 = port:PE06<2><default><default><default>
vip_csi_d3 = port:PE07<2><default><default><default>
vip_csi_d4 = port:PE08<2><default><default><default>
vip_csi_d5 = port:PE09<2><default><default><default>
vip_csi_d6 = port:PE10<2><default><default><default>
vip_csi_d7 = port:PE11<2><default><default><default>
vip_csi_sck = port:PE12<2><default><default><default>
vip_csi_sda = port:PE13<2><default><default><default>
vip_dev0_mname = "gc2035"
vip_dev0_pos = "front"
vip_dev0_lane = 1
vip_dev0_twi_id = 2
vip_dev0_twi_addr = 120
vip_dev0_isp_used = 0
vip_dev0_fmt = 0
vip_dev0_stby_mode = 0
vip_dev0_vflip = 1
vip_dev0_hflip = 1
vip_dev0_iovdd = ""
vip_dev0_iovdd_vol = 2800000
vip_dev0_avdd = ""
vip_dev0_avdd_vol = 2800000
vip_dev0_dvdd = ""
vip_dev0_dvdd_vol = 1800000
vip_dev0_afvdd = ""
vip_dev0_afvdd_vol = 2800000
vip_dev0_power_en = port:PA17<1><default><default><1>
vip_dev0_reset = port:PE14<1><default><default><1>
vip_dev0_pwdn = port:PE15<1><default><default><0>
vip_dev0_flash_en =
vip_dev0_flash_mode =
vip_dev0_af_pwdn =
vip_dev0_act_used = 0
vip_dev0_act_name = "ad5820_act"
vip_dev0_act_slave = 24
vip_dev1_mname = ""
vip_dev1_pos = "rear"
vip_dev1_lane = 1
vip_dev1_twi_id = 0
vip_dev1_twi_addr =
vip_dev1_isp_used = 0
vip_dev1_fmt = 1
vip_dev1_stby_mode = 0
vip_dev1_vflip = 0
vip_dev1_hflip = 0
vip_dev1_iovdd = ""
vip_dev1_iovdd_vol = 2800000
vip_dev1_avdd = ""
vip_dev1_avdd_vol = 2800000
vip_dev1_dvdd = ""
vip_dev1_dvdd_vol = 1500000
vip_dev1_afvdd = ""
vip_dev1_afvdd_vol = 2800000
vip_dev1_power_en =
vip_dev1_reset =
vip_dev1_pwdn =
vip_dev1_flash_en =
vip_dev1_flash_mode =
vip_dev1_af_pwdn =

[tvout_para]
tvout_used = 0
tvout_channel_num =
tv_en = 0

[tvin_para]
tvin_used = 0
tvin_channel_num =

[di_para]
di_used = 1

[mmc0_para]
sdc_used = 1
sdc_detmode = 3
sdc_buswidth = 4
sdc_clk = port:PF02<2><1><2><default>
sdc_cmd = port:PF03<2><1><2><default>
sdc_d0 = port:PF01<2><1><2><default>
sdc_d1 = port:PF00<2><1><2><default>
sdc_d2 = port:PF05<2><1><2><default>
sdc_d3 = port:PF04<2><1><2><default>
sdc_det = port:PF06<0><1><2><default>
sdc_use_wp = 0
sdc_wp =
sdc_isio = 0
sdc_regulator = "none"
sdc_power_supply = "none"

[mmc1_para]
sdc_used = 1
sdc_detmode = 4
sdc_buswidth = 4
sdc_clk = port:PG00<2><1><3><default>
sdc_cmd = port:PG01<2><1><3><default>
sdc_d0 = port:PG02<2><1><3><default>
sdc_d1 = port:PG03<2><1><3><default>
sdc_d2 = port:PG04<2><1><3><default>
sdc_d3 = port:PG05<2><1><3><default>
sdc_det =
sdc_use_wp = 0
sdc_wp =
sdc_isio = 1
sdc_regulator = "none"
sdc_power_supply = "none"
sdc_2xmode = 1
sdc_ddrmode = 1

[mmc2_para]
sdc_used = 0
sdc_detmode = 3
sdc_buswidth = 8
sdc_clk = port:PC05<3><1><2><default>
sdc_cmd = port:PC06<3><1><2><default>
sdc_d0 = port:PC08<3><1><2><default>
sdc_d1 = port:PC09<3><1><2><default>
sdc_d2 = port:PC10<3><1><2><default>
sdc_d3 = port:PC11<3><1><2><default>
sdc_d4 = port:PC12<3><1><2><default>
sdc_d5 = port:PC13<3><1><2><default>
sdc_d6 = port:PC14<3><1><2><default>
sdc_d7 = port:PC15<3><1><2><default>
emmc_rst = port:PC16<3><1><2><default>
sdc_det =
sdc_use_wp = 0
sdc_wp =
sdc_isio = 0
sdc_regulator = "none"
sdc_power_supply = "none"
sdc_2xmode = 1
sdc_ddrmode = 1

[smc_para]
smc_used = 0
smc_rst = port:PA09<2><default><default><default>
smc_vppen = port:PA20<3><default><default><default>
smc_vppp = port:PA21<3><default><default><default>
smc_det = port:PA10<2><default><default><default>
smc_vccen = port:PA06<2><default><default><default>
smc_sck = port:PA07<2><default><default><default>
smc_sda = port:PA08<2><default><default><default>

[usbc0]
usb_used = 1
usb_port_type = 2
usb_detect_type = 0
usb_id_gpio = port:PG12<0><1><default><default>
usb_det_vbus_gpio = port:PG12<0><1><default><default>
usb_drv_vbus_gpio = port:PL02<1><0><default><0>
usb_host_init_state = 1
usb_restrict_gpio =
usb_restric_flag = 0
usb_restric_voltage = 3550000
usb_restric_capacity = 5
usb_regulator_io = "nocare"
usb_regulator_vol = 0
usb_not_suspend = 0

[usbc1]
usb_used = 1
usb_drv_vbus_gpio =
usb_restrict_gpio =
usb_host_init_state = 1
usb_restric_flag = 0
usb_regulator_io = "nocare"
usb_regulator_vol = 0
usb_not_suspend = 0

[usbc2]
usb_used = 1
usb_drv_vbus_gpio =
usb_restrict_gpio =
usb_host_init_state = 1
usb_restric_flag = 0
usb_regulator_io = "nocare"
usb_regulator_vol = 0
usb_not_suspend = 0

[usbc3]
usb_used = 1
usb_drv_vbus_gpio =
usb_restrict_gpio =
usb_host_init_state = 1
usb_restric_flag = 0
usb_regulator_io = "nocare"
usb_regulator_vol = 0
usb_not_suspend = 0

[usb_feature]
vendor_id = 6353
mass_storage_id = 1
adb_id = 2
manufacturer_name = "USB Developer"
product_name = "Android"
serial_number = "20080411"

[msc_feature]
vendor_name = "USB 2.0"
product_name = "USB Flash Driver"
release = 100
luns = 3

[serial_feature]
serial_unique = 0

[module_para]
module_num = 7
module_power0 = "vcc-wifi-33"
module_power0_vol = 0
module_power1 =
module_power1_vol =
module_power2 =
module_power2_vol =
module_power3 =
module_power3_vol =
chip_en =
lpo_use_apclk =

[wifi_para]
wifi_used = 0
wifi_sdc_id = 1
wifi_usbc_id = 5
wifi_usbc_type = 1
wl_reg_on = port:PL07<1><default><default><0>
wl_host_wake = port:PG10<0><default><default><0>
wl_host_wake_invert = 0

[bt_para]
bt_used = 0
bt_uart_id = 1
bt_rst_n =
bt_wake =
bt_host_wake =
bt_host_wake_invert = 0

[pcm0]
daudio_used = 0
daudio_master = 4
daudio_select = 1
audio_format = 1
signal_inversion = 1
mclk_fs = 128
sample_resolution = 16
slot_width_select = 32
pcm_lrck_period = 32
pcm_lrckr_period = 1
msb_lsb_first = 0
sign_extend = 0
slot_index = 0
slot_width = 32
frame_width = 0
tx_data_mode = 0
rx_data_mode = 0
i2s_mclk = port:PA18<2><1><default><default>
i2s_bclk = port:PA19<2><1><default><default>
i2s_dout0 = port:PA20<2><1><default><default>
i2s_din = port:PA21<2><1><default><default>

[pcm1]
daudio_used = 0
daudio_master = 4
daudio_select = 1
audio_format = 1
signal_inversion = 1
mclk_fs = 128
sample_resolution = 16
slot_width_select = 32
pcm_lrck_period = 32
pcm_lrckr_period = 1
msb_lsb_first = 0
sign_extend = 0
slot_index = 0
slot_width = 32
frame_width = 0
tx_data_mode = 0
rx_data_mode = 0
i2s_mclk = port:PG10<2><1><default><default>
i2s_bclk = port:PG11<2><1><default><default>
i2s_dout0 = port:PG12<2><1><default><default>
i2s_din = port:PG13<2><1><default><default>

[audio0]
audio_used = 1
lineout_vol = 31
cap_vol = 5
audio_hp_ldo = "none"
adcagc_used = 0
adcdrc_used = 0
dacdrc_used = 0
adchpf_used = 0
dachpf_used = 0
audio_pa_ctrl = port:PA16<1><default><default><0>

[spdif0]
spdif_used = 0
spdif_dout = port:PA17<2><1><default><default>

[audiohub]
hub_used = 0
codec_used = 1
spdif_used = 1
hdmi_used = 1

[s_cir0]
ir_used = 0
ir_rx = port:PL11<2><1><default><default>
ir_power_key_code0 = 87
ir_addr_code0 = 40704
ir_power_key_code1 = 26
ir_addr_code1 = 64260
ir_power_key_code2 = 20
ir_addr_code2 = 32640
ir_power_key_code3 = 21
ir_addr_code3 = 32640
ir_power_key_code4 = 11
ir_addr_code4 = 63240
ir_power_key_code5 = 3
ir_addr_code5 = 239
ir_power_key_code6 = 159
ir_addr_code6 = 19635
ir_power_key_code7 = 10
ir_addr_code7 = 30536
ir_power_key_code8 = 69
ir_addr_code8 = 48386
ir_power_key_code9 = 77
ir_addr_code9 = 56865
ir_power_key_code10 = 24
ir_addr_code10 = 65025
ir_power_key_code11 = 87
ir_addr_code11 = 65280
ir_power_key_code12 = 77
ir_addr_code12 = 65344

[cir]
ir_used = 1
ir_tx = port:PH07<2><default><default><default>

[dvfs_table]
pmuic_type = 1
pmu_gpio0 = port:PL06<1><1><2><1>
pmu_level0 = 11300
pmu_level1 = 1100
max_freq = 1200000000
min_freq = 480000000
LV_count = 5
LV1_freq = 1200000000
LV1_volt = 1300
LV2_freq = 1008000000
LV2_volt = 1300
LV3_freq = 912000000
LV3_volt = 1100
LV4_freq = 648000000
LV4_volt = 1100
LV5_freq = 480000000
LV5_volt = 1100

[gpu_dvfs_table]
G_LV_count = 3
G_LV0_freq = 312000000
G_LV0_volt = 1200000
G_LV1_freq = 384000000
G_LV1_volt = 1200000
G_LV2_freq = 456000000
G_LV2_volt = 1200000

[Vdevice]
Vdevice_used = 0
Vdevice_0 = port:PH10<5><1><2><default>
Vdevice_1 = port:PH11<5><1><2><default>

[s_uart0]
s_uart_used = 0
s_uart_tx = port:PL02<2><default><default><default>
s_uart_rx = port:PL03<2><default><default><default>

[s_rsb0]
s_rsb_used = 1
s_rsb_sck = port:PL00<2><1><2><default>
s_rsb_sda = port:PL01<2><1><2><default>

[s_jtag0]
s_jtag_used = 0
s_jtag_tms = port:PL04<2><1><2><default>
s_jtag_tck = port:PL05<2><1><2><default>
s_jtag_tdo = port:PL06<2><1><2><default>
s_jtag_tdi = port:PL07<2><1><2><default>

[s_powchk]
s_powchk_used = -2147483648
s_power_reg = 0
s_system_power = 50

[sim0]
scr_used = 0
scr_vccen = port:PA06<2><default><default><default>
scr_slk = port:PA07<2><default><default><default>
scr_sda = port:PA08<2><default><default><default>
scr_rst = port:PA09<2><default><default><default>
scr_det = port:PA10<2><default><default><default>

[ts0]
tsc_used = 0
tsc_clk = port:PE00<3><default><default><default>
tsc_err = port:PE01<3><default><default><default>
tsc_sync = port:PE02<3><default><default><default>
tsc_dvld = port:PE03<3><default><default><default>
tsc_d0 = port:PE04<3><default><default><default>
tsc_d1 = port:PE05<3><default><default><default>
tsc_d2 = port:PE06<3><default><default><default>
tsc_d3 = port:PE07<3><default><default><default>
tsc_d4 = port:PE08<3><default><default><default>
tsc_d5 = port:PE09<3><default><default><default>
tsc_d6 = port:PE10<3><default><default><default>
tsc_d7 = port:PE11<3><default><default><default>

[gpio_power_key]
key_used = 1
key_io = port:PL03<6><default><default><0>

[key_para]
key_used = 0
key_cnt = 5
key1_vol = 222
key2_vol = 444
key3_vol = 666
key4_vol = 857
key5_vol = 2000

[d7s_para]
d7s_used = 0
din_gpio = port:PD00<1><default><default><1>
clk_gpio = port:PD01<1><default><default><1>
stb_gpio = port:PD02<1><default><default><1>

[mali_para]
mali_used = 1
mali_clkdiv = 1
mali_extreme_freq = 600
mali_extreme_vol = 1400

[w1_para]
w1_used = 1
gpio = 20

[corekeeper]
corekeeper_enabled = 1

 

Posted in c-opi | Tagged | Leave a comment