Archive

Archive for the ‘Coding’ Category

Conditional Assembly Language…

May 10, 2016 Leave a comment

If you’ve ever read or written a macro you have no doubt at least seen conditional assembly language. It’s all that AIF and AGO stuff that forms a sort of ‘program’ within the macro so that it can generate code or whatever depending on whatever the input parameters are.

What’s really cool though is that it is not just limited to macros, you can use it within open code as well. So you might ask ‘why would you need to do that?’ but even if you don’t ask, here’s one interesting situation that came up recently.

I had some code that used a macro to generate a DSECT to map a control block. However we were switching version of the product that supplied the macro and a field within the macro had changed names even though it’s content had not. The result was that my code would only assemble with one version of the macro since with the other one it would get a not found error for the changed label. Since I did not want to have to co-ordinate my source code change with a build tool change the problem I had was how to make my source code support both versions of the macro and DSECT that it generated?

In case you have not guessed, the answer is conditional assembly language.

Here’s an example.

The old macro/DSECT:

         MYMACRO
SOMENAME DSECT
MYFIELD  DS    CL8

The new version of the macro/DSECT

        MYMACRO
SOMENAME DSECT
NEWNAME  DS    CL8

 

 

So my code originally looked something like this:

         USING SOMENAME,R2
         CLC   MYFIELD,=CL8'AAAAAAAA'

Obviously if I switch to the new macro library, my assembly will fail since the field ‘MYFIELD’ is no longer defined within the DSECT.

However, what you can do is to test to see if the variable ‘MYFIELD’ is defined and if not then conditionally change the code that gets assembled. Thus:

         USING SOMENAME,R2
         AIF   (T'MYFIELD EQ 'U').NEWMAC
         CLC   MYFIELD,=CL8'AAAAAAAA'
         AGO   .CONT
.NEWMAC  ANOP
         CLC   NEWNAME,=CL8'AAAAAAAA'
.CONT    ANOP

 

The AIF tests to see if the ‘type’ specification for the field MYFIELD is ‘U’, that is undefined. If it is undefined that means it has not been seen by the assembler (yet) so jump to the label .NEWMAC and continue to generate the code from there, which of course generates the code using the new field label of NEWNAME.

If the field MYFIELD is not ‘undefined’ then the assembler generates the code using the old field name, MYFIELD and then jumps (AGO) to the label .CONT to continue the assembly.

As a result, no matter which version of the macro library I am using, my code still assembles and works correctly.

There are other ways of achieving the same effect; For example by using the conditional assembly language to control the redefining of the old or renamed symbol to a common name and using that common name in the open code.

One gotcha though to be aware of. The macro/DSECT has to be defined in the source code BEFORE the conditional assembly code. If it is defined after the conditional code then, since the assembler has not seen either field at the time it encounters the test for the field being defined, it will always treat it as being undefined which would cause an assembly error when using the old macro/DSECT library because it would generate the code to use the new field name.

Advertisements
Categories: Coding, Mainframe

When projects collide…

September 12, 2013 Leave a comment

The iPhone/iPad app I am developing is for live music use (not giving away any details just yet since I am sure any reasonable iPhone developer could knock up the same app in a couple of days and beat me to the finish line!) which means your hands are not so free. My original idea was to use a blue tooth connected foot pedal that I already happen to have (Airturn BT-105) to control the app. However it occurred to me that it would be pretty simple to add a blue tooth shield to an Arduino, hook up a few switches and make my own blue tooth enabled stomp box to control my app, plus I could have more than the two switches my current pedal has.

So, once the current Arduino project is done I’ll be starting on creating a blue tooth enabled stomp pedal to control this app and looking at blue tooth enabling my app to work with my custom pedal.

Categories: Coding, iPhone, xcode Tags: , , ,

Back to the iPhone project

September 11, 2013 Leave a comment

The Arduino project is on hold because I am waiting for parts to arrive which appear to be on a VERY slow boat from Thailand so I decided to get back to my iPhone project.

My iPhone app (which will be mainly an iPad app when it is done) currently has three view controllers. I guess you can think of these as logical screens. Each one has it’s own implementation file (class) and when I originally wrote things, just to get it all going I used a lot of global variables to share data between the view controllers. This got messy really quickly so I’ve been reworking the code over the past couple of weeks to get rid of the global variables and pass data between the view controllers the ‘proper’ way.

I also need to make the app support device rotation as well as both iPhone and iPad devices so for no particular reason I chose to attack the device rotation topic first. So far it is proving to be an interesting challenge to make all my view controllers  work correctly since only the currently displayed VC receives the orientation change messages so any hidden VC has to check the orientation when it is redisplayed and reconfigure the screen to match the current orientation. Let’s just say that this part of the project is still a ‘work in progress’!

I have managed to sketch out what I want the main interface to look like but all the current work is just to get to the point where I can actually implement the main app function and has nothing to do with the actual ‘guts’ of the app.

Oh, and now we have new devices (no doubt with new physical screen sizes) and a new OS to contend with as well.

Still, it keeps me off the streets at night!

Categories: Coding, iPhone Tags: , ,

Finished Code…

August 21, 2013 Leave a comment

This is the finished code for the Arduino project. I switched the code to use exclusive ORs to flip the settings and added a second switch detection block of code for the second switch. All in all, pretty easy.

I’m still waiting for some parts to arrive before I can construct the finished project but I don’t anticipate any problems other than it not physically fitting in the project box I have ordered!

#include <Bounce.h>

/*
Arduino Uno based stomp box Midi controller for T.C. Electronics M300
Copyright David E. Ellis 2013

Switch one toggle patches 2 and 3
Switch 2 toggles dry and mixed signal

 */

#define PATCH_SWITCH 4            // Pin 4 - Controls patch switch
#define BYPASS_SWITCH 5           // Pin 5 - Controls bypass (wet/dry)
#define PATCH_LED 12              // On=initial patch, off=alternate patch
#define BYPASS_LED 11             // on=bypass on (dry), off=bypass off (wet)
#define INITIAL_PATCH 2
#define ALT_PATCH 3
#define WET 0                     // Hear effect (wet signal) when bypass is off
#define DRY 127                     // dry signal when bypass on

// patch control
byte cur_patch = INITIAL_PATCH;
byte old_patch = ALT_PATCH;
byte cur_patch_led = HIGH;                            // high = led on
byte old_patch_led = LOW;

// bypass control
byte cur_bypass = DRY;                                // initial state for bypass signal is on (dry signal)
byte old_bypass = WET; 
byte cur_bypass_led = HIGH;
byte old_bypass_led = LOW;

Bounce bouncer1 = Bounce(PATCH_SWITCH,5);            // setup 5 ms debounce on switch 1
Bounce bouncer2 = Bounce(BYPASS_SWITCH,5);            // ditto on on switch 2

// the setup routine runs once when you press reset:
void setup() {   
  Serial.begin(31250);                              // Set MIDI baud rate:
  selectPatch(INITIAL_PATCH);                       // Set inital patch number
  setBypass(DRY);                                   // Set bypass to on initially (dry signal)
  pinMode(PATCH_SWITCH,INPUT_PULLUP);                // Open switch is normally pulled high
  pinMode(BYPASS_SWITCH,INPUT_PULLUP);                // Open switch is normally pulled high
  pinMode(PATCH_LED, OUTPUT);                         // initialize the led pin as an output.
  digitalWrite(PATCH_LED, cur_patch_led);              // set to current state 
  pinMode(BYPASS_LED, OUTPUT);                         // initialize the led pin as an output.
  digitalWrite(BYPASS_LED, cur_bypass_led);         // set to current state
}

// the loop routine runs over and over again forever:
void loop() {

  // Switch 1 controls the patch
  if (bouncer1.update()) {                           // returns true if switch state changed (on or off)
    if (!bouncer1.read()) {                          // if switch is pressed (input low)
      cur_patch=cur_patch^old_patch;                 // swap patch
      old_patch=old_patch^cur_patch;
      cur_patch=cur_patch^old_patch;
      selectPatch(cur_patch);                        // send it
      cur_patch_led=cur_patch_led^old_patch_led;    // swap led status
      old_patch_led=old_patch_led^cur_patch_led;
      cur_patch_led=cur_patch_led^old_patch_led;
      digitalWrite(PATCH_LED,cur_patch_led);        // send it
    }
  }

  // Switch 2 controls bypass (wet/dry mix)
  if (bouncer2.update()) {                           // returns true if switch state changed (on or off)
    if (!bouncer2.read()) {                          // if switch is pressed (input low)
      cur_bypass=cur_bypass^old_bypass;              // swap bypass state
      old_bypass=old_bypass^cur_bypass;
      cur_bypass=cur_bypass^old_bypass;
      setBypass(cur_bypass);                           // and set new state
      cur_bypass_led=cur_bypass_led^old_bypass_led;     // swap led status
      old_bypass_led=old_bypass_led^cur_bypass_led;
      cur_bypass_led=cur_bypass_led^old_bypass_led;
      digitalWrite(BYPASS_LED, cur_bypass_led);         // and send it
      }      
    }
  }  

void selectPatch(byte patchNum) {
  Serial.write(0xC0);                    // change patch command
  Serial.write(patchNum-1);              // patch '1' is really zero etc
}

void setBypass(byte mix) {
  Serial.write(0xB0);                    // CC
  Serial.write(0x51);                    // 81 - Bypass
  Serial.write(mix);                     // by on (127/dry) or off (0/wet)   
}
Categories: Coding, Development Tools Tags:

As if I don’t have enough projects….

August 14, 2013 Leave a comment

I’ve been playing around with an Arduino micro processor to build a small midi foot controller/stomp box for an effects unit in my synth rack unit. I just need it to be able to make the effects unit flip flop between two patches and also switch from a dry to a mixed signal.

This is the circuit for my prototype (just one switch so far to switch the patches):

ArduinoMidiSwitchCircuitAnd this is the code (oh look, more C!):

#include <Bounce.h>

/*
Midi controller for M300
Switch one toggle patches 2 and 3
Switch 2 toggles dry and mixed signal
 */

#define SWITCH1 4           // header P4, pin 3 - Controls patch switch
#define LED 13              // on board led on pin 13
#define INITIAL_PATCH 2
#define ALT_PATCH 3

  int patch = INITIAL_PATCH;

Bounce bouncer1 = Bounce(SWITCH1,5);    // setup 5 ms debounce on switch 1

// the setup routine runs once when you press reset:
void setup() {   
  Serial.begin(31250);                  //  Set MIDI baud rate:
  selectPatch(INITIAL_PATCH);           // Set inital patch number
  pinMode(SWITCH1,INPUT_PULLUP);        // Open switch is normally pulled high
  pinMode(LED, OUTPUT);                 // initialize the led pin as an output.
  digitalWrite(LED, HIGH);              // led on = initial patch  
}

// the loop routine runs over and over again forever:
void loop() {

  if (bouncer1.update()) {               // returns true if switch1 state changed (on or off)
    if (!bouncer1.read()) {              // if switch is pressed (input low)
      if (patch == INITIAL_PATCH) {      // if current patch = initial patch
        selectPatch(ALT_PATCH);          // swap to alt patch
        patch=ALT_PATCH;                 // remember it
        digitalWrite(LED, LOW);          // led off = alt patch
      }
      else {                             // current patch = alt patch
        selectPatch(INITIAL_PATCH);      // swap to inital patch
        patch=INITIAL_PATCH;             // remember it
        digitalWrite(LED, HIGH);         // led on = inital patch
      }      
    }
  }

}

void selectPatch(int patchNum) {
  Serial.write(0xC0);                    // change patch command
  Serial.write(patchNum-1);              // patch '1' is really zero etc
}

I am going to look at using Exclusive ORs to replace the ‘state’ code and LED flip flopping but for now this works very well. Hook up another switch, bit more code and the prototype will be done.

Total turn around time so far to get to this point (including installing the compiler and research), about an hour!

Makes the iPhone programming look ridiculously hard (still trying to figure out how to fix a memory leak. I know where it is, just not how to fix. very frustrating!).

Categories: Coding, Development Tools Tags:

Upgraded my ‘virtual Mac’…

August 4, 2013 1 comment

I’ve been using an Xcode plan from http://virtualmacosx.com/ for a little while but now I need to be able to install other software so that I can generate data for my app and the trouble with the Xcode plan is that you don’t have admin authority. They did say they could install anything I needed but there are a number of other limitations with the Xcode plan that mean that while it has been great for getting started with iOS development, it’s now time to upgrade to a more serious plan.

So I’ve gone for one of their Virtual Private Desktop plans. My wife did  say I could go and get a Mac but I figure that since I am still not totally committed to this yet and still in ‘play’ mode pretty much, I could buy a LOT of months on a virtual machine for the price of a new iMac (plus I object to paying a premium for ‘style’). There are other advantages to the new plan too apart from more storage and more memory. I can use TeamViewer to connect to the desktop instead of vanilla VNC. TeamViewer is free for non commercial use (which this definitely is right now), it performs better than VNC and has encryption, something that I was never able to enable using VNC to the Xcode desktop. The new image also has ADMIN privileges so I can install stuff from iTunes! and since it is a personal desktop, not shared like with the Xcode plan, the iOS simulator is no longer shared. not that it was ever an issue for me but I don’t have to shut it down after every use now either.

The hardest part of the whole process was probably transferring my development certificates from the old Xcode machine to this new one. Apple seem to be as useless as everyone else in explaining this whole process in terms a numbskull like me can understand but I seem to have managed it now. I rebuilt my app on the new machine and managed to install it on my iPod and run it so I ‘think’ I am good to go.

Anyway I’ve ‘committed’ to the new environment by cancelling my Xcode plan from the next billing cycle which is  in a few days. After that, if I messed up, I gotta fix it the hard way (or hope I backed it up!).

Mixing it up with C and assembler with METALC (Part 2)…

July 29, 2013 Leave a comment

Following on from my earlier post, here’s a version of the reverse string program that is ‘closer’ (but still no cigar yet):

                                                   
#include <stdio.h>                                                      
#include <stdlib.h>                                                     
#include <string.h>                                                     

char * reverse( char * in) {                                            
    int l = strlen(in);                                                 
    char * work;                                                        

    if (l>0) {                                                          
    work = malloc(l);        // get a temp work area                    
       __asm(                                                           
         "      PUSH  USING                     \n"                     
         "      DROP  ,                         \n"                     
         "      BASR  4,0                       \n"                     
         "      USING *,4                       \n"                     
         "      LR    1,%1     LENGTH           \n"                     
         "      LA    2,%0     TARGET           \n"                     
         "      LA    3,%2     SOURCE           \n"                     
         "      BCTR  1,0                       \n"                     
         "      LA    3,0(1,3) LAST CHAR of SRC \n"                     
         "      EX    %1,MVCIN                  \n"                     
         "      J     PASTMOVE                  \n"                     
         "MVCIN MVCIN 0(0,2),0(3)               \n"                     
         "PASTMOVE DS 0H                        \n"                     
         "      POP   USING                     \n"                     
         :"=m"(work) : "r"(l), "m"(in)                                  
         :"r1", "r2","r3","r4"                                          
       );                                                               
    memcpy(in,work,l);       // copy reversed string in work to orig    
    free(work);              // release work area                       
    }                        // input area                              

    return in;               // return same string back to caller       
}                                                                       

int main()                                                              
{                                                                       
   char c[21]="12345";             // String to reverse                 

   printf("input=($s)",c);         // print input string                
   reverse(c);                     // reverse it in place               
   printf("output=($s)",c);        // print revered string              

   return 0;                                                            
}

At Least this compiles although it will not link edit because it seems there is NO printf function in Metal C!

You can see that my little one line of assembler has become somewhat longer as a result of the way you have to pass parameters into the embedded code and the fact that since the MVCIN instruction has the move length encoded in the instruction at assembly time, the only way to make it variable is to use an EXECUTE instruction. I also had to mess around with code base registers and assign this little bit of code it’s own base register so that the execute instruction has addressability to the MVCIN instruction.

At least I added some length checking code so that it did not try to do with move with a zero length which would of course result in a 256 character move and resultant storage overlay.

Still an interesting exercise though.

Categories: Coding, Mainframe