Netduino home hardware projects downloads community

Jump to content


The Netduino forums have been replaced by new forums at community.wildernesslabs.co. This site has been preserved for archival purposes only and the ability to make new accounts or posts has been turned off.
Photo

C# help


  • Please log in to reply
35 replies to this topic

#21 Mario Vernari

Mario Vernari

    Advanced Member

  • Members
  • PipPipPip
  • 1768 posts
  • LocationVenezia, Italia

Posted 09 March 2011 - 08:43 AM

Additional info, just for fun...
Posted Image
Posted Image

Mario
Biggest fault of Netduino? It runs by electricity.

#22 CW2

CW2

    Advanced Member

  • Members
  • PipPipPip
  • 1592 posts
  • LocationCzech Republic

Posted 09 March 2011 - 10:01 AM

But I could't find any useful implementation or API to get or set binary values like I can do in C.

Unfortunately, the current implementation of .NET Micro Framework does not contain neither BitArray nor BitVector32 (they may be considered for future versions), but you can use &,|,~,^ bitwise operators as you know them from C/C++:

if((bits & 0x01) == 0x01) // Test 0. bit
{
  bits |= 0x80; // Set 7. bit
}
else
{
  bits &= ~0x02; // Clear 1. bit
}

You can pack up to 32 bits in 'int', resp. 64 bits in 'long' variables, and you can use byte/int/long array to store more bits or emulate bit matrices.

byte[] array100bits = new byte[(100+7)/8]; // Round up to whole bytes

void SetBit(byte[] bits, int index, bool value = true)
{
  var byteIndex = index/8;
  var mask = (byte)(1 << (index % 8));
  if(value)
  {
 	bits[byteIndex] |= mask;
  }
  else
  {
 	bits[byteIndex] &= (byte)~mask; // Note: ~ operator converts to int
  }
}

const int M = 10;
const int N = 10;
byte[] matrix = new byte[(M*N + 7)/8];

void SetBit(int x, int y, bool value = true)
{
  // TODO: Parameter validation (omitted for the sake of clarity)
  SetBit(matrix, x + y*M, value);
}
Note: The actual formulas may vary depending on the size of array element, padding, 'coordinate system' etc.

#23 Ruff

Ruff

    New Member

  • Members
  • Pip
  • 9 posts

Posted 09 March 2011 - 03:29 PM

Wow, This is such a nice Forum with friendly helping Members. @Mario from where do you get this Output Files which look like Assembler? Do You have to decompile what is on Netduino? This is really interesting. @CW2 Thanks to clearify that. Is it actually C# Code? these 'var mask' or 'var byteIndex' looks more like JavaScript while I think this is the key to store bits into an Int. I'll have a look at it... my main Problem stays: I didn't see Bytes in an array of byte[][] in my Debugger. What can I do to fix that? Is it because of .Net Micro or because of VS-Express Edition?? I even can't find watches.

#24 Mario Vernari

Mario Vernari

    Advanced Member

  • Members
  • PipPipPip
  • 1768 posts
  • LocationVenezia, Italia

Posted 09 March 2011 - 03:41 PM

ok, this is clear enaugh now. How I can solve my Problem with the Debugger showing '?' as values for my Bytes?


Sorry, but I did not understand where the debugger shows you "?" instead of the byte value.
Mario
Biggest fault of Netduino? It runs by electricity.

#25 Ruff

Ruff

    New Member

  • Members
  • Pip
  • 9 posts

Posted 09 March 2011 - 05:14 PM

Sorry, but I did not understand where the debugger shows you "?" instead of the byte value.
Mario

In my Code if I'm debugging arrays of arrays of Byte. Looks for example like this
http://img845.images.../debuggerc.png/

seems, that I'm not allowed to uplad Image Data, so I insert the link

#26 Mario Vernari

Mario Vernari

    Advanced Member

  • Members
  • PipPipPip
  • 1768 posts
  • LocationVenezia, Italia

Posted 10 March 2011 - 06:39 AM

I'm sorry, but I did not realize that you have posted me some other questions: here we go.

About the (jagged) array.
I checked the picture and your code. It seems that you have placed a breakpoint just *before* the evaluation of "shiftPattern": the break stops *before* executing that line. So far, the debugger shows an undefined jagged array.
IMHO, jagged arrays are something confusing, without strong rule: there's very few compile-time checking support. I'd prefer 1000 times better somethink like this:

public class PatternRow
{
  private static int[] ColumnMask = new int[]
  {
    0x01,
    0x010,
    0x0100,
    0x01000,
    0x010000,
  }

  public PatternRow(params int[] rows)
  {
    this._rows = rows;
  }

  private int[] _rows;

  public bool GetCell(int row, int column)
  {
    int row = this._rows[row];
    return (row & ColumnMask[column]) != 0;
  }
}

public class FiveToSevenPattern : DotMatrixPattern
{
  
  // ...

  public PatternRow A = new PatternRow(
    0x11111,
    0x10001,
    0x10001,
    0x10001,
    0x11111,
    0x10001,
    0x10001);
  
  // ...

}
Thus your code should be different than now, but it looks much more elegant and error-proof.
I guess that eats much less memory because there are lots of array missing. However you may avoid even the array in the PatternRow class.

About VS Express, the answer is "NO". Basically, the difference between Express and $$$ versions, are on the quantity of satellite tools, plugins and whatever else. For home work I use Express and I've done very huge professional apps too. $$$ version (I'm using at office) is more straightforward for certain functions...Anyway, as far I know, there is *NO* less core functionality in the Express edition.

IL-Disassembler.
The disassembly could be easily done via MSIL Disassebler tool, that comes free with the Windows SDK. Search in the internet for the download.
http://msdn.microsof...1k1(VS.80).aspx
NOTE: these are *NOT* the native CPU opcodes, but the portable-instructions generated by the C# compiler. In the .Net framework there is a Just-in-time (JIT) compiling of these opcodes to native code. In the Net Micro that post-compilation is made at the deploy phase, I think.

var.
The reason for the "var" statement is quite confusing if you have few friendship with C#. There's *NO* relation with Javascript.
I'd suggest to avoid using "var", until you have enough experience with the language.
By the way, "var" is the "lazy programmers" shortcut to the generics.

Cheers
Biggest fault of Netduino? It runs by electricity.

#27 Corey Kosak

Corey Kosak

    Advanced Member

  • Members
  • PipPipPip
  • 276 posts
  • LocationHoboken, NJ

Posted 10 March 2011 - 04:25 PM

I think this (and all the of the suggestions so far) are rather poor ideas because they all use far too much code space. When we mean to evaluate a given approach, one important question we ought to ask is how much does it cost per character. If this code is intended to support a whole character set, this is going to be a very important concern. For PatternRow, my measurements are below (I have changed FiveToSevenPattern into a static class):

public class Program {
  public static void Main(string[] args) {
  }

  public class PatternRow {
    public PatternRow(params int[] rows) {
      this._rows = rows;
    }

    private int[] _rows;
  }

  public static class FiveToSevenPattern {
    public static PatternRow A=new PatternRow(
      0x11111,
      0x10001,
      0x10001,
      0x10001,
      0x11111,
      0x10001,
      0x10001);

#if false
    public static PatternRow B=new PatternRow(
      0x11110,
      0x10001,
      0x10001,
      0x10010,
      0x10001,
      0x10001,
      0x11110);
#endif

#if false
    public static PatternRow C=new PatternRow(
      0x01111,
      0x10000,
      0x10000,
      0x10000,
      0x10000,
      0x10000,
      0x01111);
#endif

#if false
    public static PatternRow D=new PatternRow(
      0x11110,
      0x10001,
      0x10001,
      0x10001,
      0x10001,
      0x10001,
      0x11110);
#endif
  }
}

  • As shown: 504 bytes
  • With B enabled: 580 bytes
  • With B and C enabled: 660 bytes
  • With B,C,D enabled: 736 bytes
Conclusion: somewhere between 76 and 80 bytes per character. This is a pretty inefficient representation.

(For all the measurements I'm referring to the size of the .pe file which is what gets deployed to the device)

You probably really ought to compile the binary data offline and store it in an embedded resource. However, if you really want to pack it into a nice-looking C# source array, I believe that the following is the best you can do:

public class Program {
  public static void Main(string[] args) {
  }


  public static class AllPatterns {
    //note that at the moment most of these constants are currently unused
    //but I include them here for completeness

    private const byte _____=0x00;
    private const byte ____X=0x01;
    private const byte ___X_=0x02;
    private const byte ___XX=0x03;
    private const byte __X__=0x04;
    private const byte __X_X=0x05;
    private const byte __XX_=0x06;
    private const byte __XXX=0x07;
    private const byte _X___=0x08;
    private const byte _X__X=0x09;
    private const byte _X_X_=0x0A;
    private const byte _X_XX=0x0B;
    private const byte _XX__=0x0C;
    private const byte _XX_X=0x0D;
    private const byte _XXX_=0x0E;
    private const byte _XXXX=0x0F;
    private const byte X____=0x10;
    private const byte X___X=0x11;
    private const byte X__X_=0x12;
    private const byte X__XX=0x13;
    private const byte X_X__=0x14;
    private const byte X_X_X=0x15;
    private const byte X_XX_=0x16;
    private const byte X_XXX=0x17;
    private const byte XX___=0x18;
    private const byte XX__X=0x19;
    private const byte XX_X_=0x1A;
    private const byte XX_XX=0x1B;
    private const byte XXX__=0x1C;
    private const byte XXX_X=0x1D;
    private const byte XXXX_=0x1E;
    private const byte XXXXX=0x1F;

    public static readonly byte[] data=
    {
      _XXX_ ,
      X___X ,
      X___X , 
      X___X ,
      XXXXX ,
      X___X ,
      X___X ,

#if false
      XXXX_ ,
      X___X ,
      X___X ,
      XXXX_ ,
      X___X ,
      X___X ,
      XXXX_ ,
#endif

#if false
      _XXXX ,
      X____ ,
      X____ ,
      X____ ,
      X____ ,
      X____ ,
      _XXXX ,
#endif

#if false
      XXXX_ ,
      X___X ,
      X___X ,
      X___X ,
      X___X ,
      X___X ,
      XXXX_ ,
#endif
    };
  };
}
Here are the stats for this representation:
  • As shown (with only A enabled): 588 bytes
  • With B enabled: 600 bytes
  • With B and C enabled: 604 bytes
  • With B,C,D enabled: 612 bytes
  • ...
  • With 101 character entries: 1292 bytes

...which averages out to 7 bytes per character which is what you would expect. You can find a given character at an array offset = (7 times its index)

I'd suggest to avoid using "var", until you have enough experience with the language.
By the way, "var" is the "lazy programmers" shortcut to the generics.

I disagree with both points. var is a very intuitive and productivity-enhancing language feature which has nothing in common with generics. If you're in a situation where you're uncertain about what type your variable has, just hover your mouse pointer over the word "var". Using var is not a sign of laziness but instead an acknowledgement of the fact that computers are supposed to work for humans, rather than the other way around.

#28 Mario Vernari

Mario Vernari

    Advanced Member

  • Members
  • PipPipPip
  • 1768 posts
  • LocationVenezia, Italia

Posted 10 March 2011 - 04:54 PM

@Corey
I agree totally on the solution pre-compiled: it would be the best. Your solution is somewhere elegant though.

About "var".
I know how/when use the "var", but a novice programmer could fall easily to confusion: that is what I have noticed among my friends.
Let's take an example:

var b = false;
var d = 12;
var i = 3.14;
var t = "Hello!";
Here is pretty straightforward that "b is boolean" and "t is string". Maybe you may also understand that "i is real"...but float, double or decimal?
You *must* know that is a double, otherwise there'll be a suffix.

Another common question about "var" is:

class C
{
  var id = "ciao";  //no doubt that is a string!
}
why can not I write that, but inside a routine do?
http://blogs.msdn.co...-on-fields.aspx
That's confusing for novice people, so I'd prefer to unsuggest to Ruff (he's comparing to Javascript "var"...)

By other hands, when I write:

var result = from item in collection
             group item by item.Key into g
             select new { Id=g.Key, Items=g }
...it's *not* straightforward to understand what is the type of result and -more- it would be less readable.
That is *my* opinion and your's is fully respectable indeed.

Cheers
Mario
Biggest fault of Netduino? It runs by electricity.

#29 Ruff

Ruff

    New Member

  • Members
  • Pip
  • 9 posts

Posted 13 March 2011 - 10:39 PM

Hey, Sorry, that I couldn't reply yet, my ISP is making me sick... I like the solution Corey gives me. But I have a logical problem with it: If I want to "shift" the Letters from right to left, to "print" a text on it, I have to calculate 5 times for every letter what will be the next byte const to show in that row. example: Case: I wanna print letters A and B. First Row on A = '_XXX_=0x0E'; First Row of B = 'XXXX_=0x1E'; To switch them I need 5 states between (4 for columns(2-5), 1 for space between): 1. _XXX_=0x0E //normal first row from A 2. XXX__=0x1C //1. Row from A switched with one space 3. XX__X=0x19 //as above but last column is first column of B 4. X__XX=0X13 //as above but with first and second column of B 5. __XXX=0x07 6. _XXXX=0x0F 7. XXXX_=0x1E // first row of B I see no real correlation of these Values or how to get the next 'X' or '_' from column[x] of B to calculate what will be the next row const to show. Is there an algorithm I have missed? Thats the reason I had used arrays of arrays. Now I'm thinking about writing my own struct to solve that problem. Like CW2 said, to store 64 bits in a long, enables me, to save the whole Pattern inside a long Variable.

#30 Corey Kosak

Corey Kosak

    Advanced Member

  • Members
  • PipPipPip
  • 276 posts
  • LocationHoboken, NJ

Posted 13 March 2011 - 11:32 PM

I see no real correlation of these Values or how to get the next 'X' or '_' from column[x] of B to calculate what will be the next row const to show.

You just need to do some simple bit manipulations. Does this program help you to see what needs to be done?
using Microsoft.SPOT;

public class Program {
  public static void Main(string[] args) {
    for(var j=0; j<7; ++j) {
      Show(0x0E, 0x1E, j);
    }
  }

  private static void Show(int byte0, int byte1, int shift) {
    var leftByte=byte0<<shift;
    var rightByte=byte1>>(6-shift);
    var result=(leftByte|rightByte)&0x1f;
    Debug.Print("0x"+MakeHex((byte)result));
  }

  private static string MakeHex(byte b ) {
    const string digits="0123456789ABCDEF";
    return ""+digits[b>>4]+digits[b&0xf];
  }
}

Output:
0x0E
0x1C
0x19
0x13
0x07
0x0F
0x1E


#31 Ruff

Ruff

    New Member

  • Members
  • Pip
  • 9 posts

Posted 14 March 2011 - 02:28 PM

:unsure: :unsure: :unsure: :unsure: I can only look at it, and feel frustrated. If i try to understand whats going on I find my brain hangin in an infinite recursive loop <_< let me try to explain what I understand so far: I have byte 0x0E which is a binary representation of 00001110; and 0x1E which is 00011110. so second Show is called(byte0 = 0x0E,byte1 = 0x1E,shift = 1): var leftByte=byte0<<shift; // makes 00011100 var rightByte=byte1>>(6-shift); // makes 00000000 var result=(leftByte|rightByte)&0x1f; // =( (00011100)&00011111 ) == 00011100 == 1C.... third show called(byte0 = 0x0E,byte1 = 0x1E,shift = 2): var leftByte=byte0<<shift; // makes 00111000 var rightByte=byte1>>(6-shift); // makes 00000001 var result=(leftByte|rightByte)&0x1f; // =( (00111001)&00011111) ) == 00011001 == 0x19 WOW THATS Where the magic appears.While I'm beginning to understand that and how it works but not really why. Anyway I will try and tell you, if it works. IF it works i think this solution is freakin elegant... Thanks for the big help Ahh one further Question to these 'var': what is the benefit in THIS example to use 'var leftByte=byte0<<shift;' than: 'byte leftByte=byte0<<shift;' isn't it really clear that we will get a byte as return value? Or is the 'real' result of leftByte=0x0E<<1 == 000111000, so one bit too much for byte and we have to sign it as var instead of converting it?

#32 Corey Kosak

Corey Kosak

    Advanced Member

  • Members
  • PipPipPip
  • 276 posts
  • LocationHoboken, NJ

Posted 15 March 2011 - 02:10 AM

:unsure: :unsure: :unsure: :unsure:
I can only look at it, and feel frustrated.

Let's see if I can demystify it. I'm probably being too verbose here, but probably better to provide too much rather than too little detail.

byte0 is some 5-bit sequence of bits, say, abcde
byte1 is also a 5-bit sequence of bits, say, vwxyz

Your goal is to display some 5-bit subsequence of abcde0vwxyz (notice the 0 in there because you want a 'space' between them)

As a first step, we can form abcde0vwxyz with this expression

var temp=(byte0<<6) | byte1;

Now, to extract the proper 5-bit subsequence we want to shift abcde0vwxyz in such a way that the 5 bits we want are in the five rightmost positions:
  • if shift is 0, we want to shift our pattern right 6 (forming abcde)
  • if shift is 1, we want to shift it right 5 (forming abcde0, whose 5 rightmost bits are bcde0)
  • if shift is 2, we want to shift it right 4 (forming abcde0v, whose 5 rightmost bits are cde0v)
  • etc...

Now, since 0 goes to 6, 1 goes to 5, etc, the formula for the amount to shift right is (6-shift)

Therefore we need to shift temp to the right by this amount:

var temp2=temp>>(6-shift);
...and finally we want to mask off the low 5 bits

var result=temp2&0x1f;

Putting it all together:
var temp=(byte0<<6) | byte1;
var temp2=temp>>(6-shift);
var result=temp2&0x1f;
Now we can try to 'optimize' this code by combining temp and temp2:

var temp2=(byte0<<6 | byte1) >> (6-shift)

expands to

var temp2=(byte0<<6) >> (6-shift)
          |
          byte1 >> (6-shift)
which expands to
var temp2=((byte0 << 6) >> 6) >> -shift
          |
          byte1 >> (6-shift)

which finally simplifies to (because the 6's cancel and because a negative shift reverses the direction of the >> operator)
var temp2=(byte0 << shift) | (byte1>>(6-shift))
which should look enough like my code that you can take it from there (don't forget to mask with 0x1f at the end).

Regarding var, most of the time you want to use 'byte' is to save space (e.g. because you have an array of 1000 bytes. It usually isn't very useful to use byte as a local variable type (unless you really care about the numerical behavior of 8-bit unsigned math operations) because ints are at least as fast, if not faster, and generally won't take up any more space when used as local variables. So in this case I use var so the language can default to whatever it wants to do and I do the casting to 'byte' at the end if my program needs it.

#33 Foozinator

Foozinator

    Member

  • Members
  • PipPip
  • 16 posts

Posted 15 March 2011 - 02:17 AM

...
what is the benefit in THIS example to use
'var leftByte=byte0<<shift;'
than:
'byte leftByte=byte0<<shift;'
isn't it really clear that we will get a byte as return value? Or is the 'real' result of leftByte=0x0E<<1 == 000111000, so one bit too much for byte and we have to sign it as var instead of converting it?


It is clear that the values are bytes, but the use of "var" is harder to read (i.e. not as obvious to someone who didn't write the code as reading the more specific "byte"). The compiler may or may not see the overflow in your last example. My guess is that it wouldn't, but I've been surprised before.

So, in THIS example, it's not a good use of var. In fact, there may not be a good reason for using var in the Compact Framework. If you get involved with the full-blown .Net Framework, however, there are cases where the use of var can save some significant typing. (If you're curious, look up LINQ and anonymous types.)

#34 Corey Kosak

Corey Kosak

    Advanced Member

  • Members
  • PipPipPip
  • 276 posts
  • LocationHoboken, NJ

Posted 15 March 2011 - 02:55 AM

It is clear that the values are bytes,


In fact the types are ints. I don't use the byte type until the very end of the routine where I need it. I daresay this makes the code clearer since there isn't any monkey business with any type other than int until the end.

The reluctance to use var seems to be a cultural thing that I don't understand. In case there is any doubt about my own vote, it is wholeheartedly on the side of using it everywhere that one can. The IDE stands ready to tell you what type a variable is simply by hovering your mouse over the word 'var'. Anyway, maybe someone wants to start a separate 'var' thread on this forum where we can argue the point.

  private static void Show(int byte0, int byte1, int shift) {
    var leftByte=byte0<<shift;
    var rightByte=byte1>>(6-shift);
    var result=(leftByte|rightByte)&0x1f;
    Debug.Print("0x"+MakeHex((byte)result));
  }


#35 Mario Vernari

Mario Vernari

    Advanced Member

  • Members
  • PipPipPip
  • 1768 posts
  • LocationVenezia, Italia

Posted 15 March 2011 - 05:09 AM

In fact the types are ints. I don't use the byte type until the very end of the routine where I need it. I daresay this makes the code clearer since there isn't any monkey business with any type other than int until the end.

Corey, we both know that wasn't a byte but an int instead. The "problem" is about the reader, especially when he doesn't know so well the language and what's behind.
From my viewpoint, the absolute priority on a program source is the readiness. .Net allows to build huge applications keeping well-ordered your work even with hundreds of modules. When I take a peek to a function, I'd like to understand at a glance what it does.
As for me this sounds like why Linq is usually preferable than a simple foreach: Linq is a lot slower, eats more memory, etc.
But...it's *very* clear!...

The reluctance to use var seems to be a cultural thing that I don't understand.

It is not a reluctance, but some good practice says that you should keep always clear the data involved in whatever operation.

The IDE stands ready to tell you what type a variable is simply by hovering your mouse over the word 'var'.

The IDE could be an help, but not a "must". If you were posting a code in this forum, what kind of tip may I have?

Anyway, I fully respect your viewpoints: my habit is just to use "var" wherever is clear and/or convenient.
Tell me, if you were a student learning C#, don't you wonder why these lines are not legal?

class Foo
{
  private var _name = "Corey";      //not legal
  private string _country = "USA";  //OK
  
  void DoWork(var optionalField = 3.14159d)  //not legal
  {
    // ...
  }
}
Cheers
Mario
Biggest fault of Netduino? It runs by electricity.

#36 Corey Kosak

Corey Kosak

    Advanced Member

  • Members
  • PipPipPip
  • 276 posts
  • LocationHoboken, NJ

Posted 15 March 2011 - 01:19 PM

I've taken the liberty of moving my reply to a separate topic, so that readers of this topic don't get bored/annoyed with all of our back-and-forth. That new topic is here




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users

home    hardware    projects    downloads    community    where to buy    contact Copyright © 2016 Wilderness Labs Inc.  |  Legal   |   CC BY-SA
This webpage is licensed under a Creative Commons Attribution-ShareAlike License.