SD-Card performance data

I got myself some SDcards and decided to measure how they perform with writes using an OM-1 camera and reading out of a macbook laptop. The camera has a 90 frames buffer, and supports SDXC and UHS-2 cards (see the types of SD Cards). I set it in high speed shooting and monitored the noise of the snapshots.

The read performance is limited by the MacBook, so I will try again with a fast modern desktop. The test was to copy 100 photos generated by the write test, or about 3.3GB. A USB-2 port has a max I/O performance of 480Mbps or 60MB/s, and the cards were able to deliver it.

The write performance varies by cards. Some have even throughput that more or less fast, and some (*) have uneven throughput where the snapshots lag varies.

CardCostReadBuffering writesSteady writesFlush writes
ONN 128GB SDXC-1
class-10 3 100mb/s read
N/A65MB/s13s2.2 pic/s40s
Kootion pro 128GB
micro SDXC-1 3 A1 V30
$14
$0.11/GB
54MB/s13s1.8 pic/s*92s
Lexar professional 256GB
micro SDXC-1 UHS-II class-10 3 V60 1000x 150MB/s read 90MB/s write
$56
$0.22/GB
62MB/s12s2.8 pic/s*42.5s
Lexar E-series 512GB sSDXC-1
UHS-1 class-10 3 A1 V30 100MB/s read
$49
$0.10/GB
64MB/s13s1.8 pic/s92s
Lexar Professional 1667x 128GB SDXC UHS-II Cards, 250MB/s Read
LSD128CBNA16672
$59/2
$0.23/GB
52MB/s14.5s3pic/s30s

I’m not sure if I should be impressed by my legacy ONN SDcard, or appalled by the “pro” cards performance. Overall all these cards will work for my camera I think. I will never want to shoot that many photos per seconds. The new V rating did not husher new faster cards.

The Lexar Pro 1667X seems to be the best performer but is not a micro-SD card. The 1/2TB Lexar E is a good value and performs well enough for most needs.

Network cable standards

Since it’s hard to find what transmission speeds work with which cable and I found a reference by someone who seems very knowledgeable, I’m copying performance data here verbatim in case the site disappears. I’m also adding more generic information about lan cables. I did not come up with anything below.

Wiring

Transmission performance depends on amounts of shielding and twisting.

Applications

Network cables will have different fire resistance and toxic smoke ratings based on their application: outdoors, indoors patch cable, ceiling or in wall between floors. Look at CM, CMR (riser) and Plenum (fake ceilings in offices) ratings.

Speed vs Distance

https://serverfault.com/questions/500859/new-office-cabling-should-we-use-cat7-or-cat6a
answered Apr 19 ’13 at 13:17 by Chris S

    |100Mb|  1Gb   | 10Gb   | 40Gb†  | 100Gb‡ | Bandwidth
CAT | 100m|37m|100m|55m|100m|50m|100m|15m|100m| MHz|
    | RJ  | RJ| RJ | RJ| RJ | GG| GG | GG| GG |    |
 5  |  x  | x |    |   |    |   |    |   |    | 100|
 5e |  X  | X |  X |45m|    |   |    |   |    | 100|
 6a |  X  | X |  X | X | X  |   |    |   |    | 500|
 7† |  x  | x |  x | x | x  | x‡|    | x‡|    | 600|
 7a†|  X  | X |  X | X | X  | X†| X‡ | X†|10m‡|1200|
 81‡|  X  | X |  X | X | X  | X†| X‡ | X†|30m‡|1600|
 82‡|  X  | X |  X | X | X  | X†| X‡ | X†|50m‡|2000|

Note: some sites mention 45m not 55m as the 10Gbps limit for cat5e. Cat6 and Cat7 are moot. Below is a chart from a different site (assumes 100m rating) with legacy cables. Note that some people carry 10MBps over old phone lines.

Legend:

  • Unless otherwise noted: The specification has been formalized and accepted. Keep in mind that the end-to-end cabling needs to be rated according to the category or you can expect reduced distance (since it’s a digital system it normally either works or doesn’t, though you can limit the speed of the connection to possibly allow functionality).
  •  These are draft specifications. No guarantees, but it’s reasonably safe to assume the final specification will be substantially similar.
  •  There is some reasonable speculation that with advances in circuity these connections will be possible. However, with current technology they do not work.

Notes:

  • Cat7 is officially known as CatF, and Cat7a as CatFa, in the current draft. This may change to be consistent with the previous numbering scheme, or they may keep the letter designation.
  • 40GbE and faster does not use the RJ45 connection, it uses GG45. There is a connector known as ARJ45 which has pins for both, and is intended to be an intermediate step.
  • I’ve seen cables advertized as Cat7/Cat7a without the GG45 or ARJ45 ends, these may be just Shielded lower grade cables since there is no “7” yet. There is no official specification to which manufacturers would have to adhere.

Connector

RJ45 has 8 pins aligned. The wires strips will be shorter with CAT6 vs CAT5 standards to minimize crosstalk within the plug, plus some staggering and maybe more metal shielding.

GG45 is metal for insulation plus has 4 extra pins at the bottom to separate the signals. The 4 center pins are just backwards RJ45 compatible pins.

Data encoding

https://serverfault.com/questions/438907/what-is-the-clock-frequency-inside-10gb-and-100gb-ethernet-cards

answered Oct 16 ’12 by Chris S

A touch of terminology: baud, most people will remember that term from the days of telephone modems, is the symbol rate at which a communications medium is operating. A symbol can contain more than one bit, so sending multibit symbols allows higher throughput at lower frequencies.

  • 10MbE (10Base-T) used a very simple inverted Manchester encoding, 10 Mbaud, and a single -2.5v/2.5v differential pair for communications in each direction.
  • 100MbE (100Base-TX) used 4B/5B encoding, 125 Mbaud, and a single -1.0/1.0v differential pair for communication in each direction. So 4/5b * 125 MHz = 100Mb in each direction.
  • 1GbE (1000Base-T) uses PAM-5 TCM, the same 125 Mbaud as 100MbE, all four -1.0/1.0v differential pairs for communication in both directions at the same time. The PAM-5 coding allows for 5 states, but the trellis modulation limits each end to 2 at any given time, so 2 bits are sent in each symbol. Thus 125M/s * 4 * 2b = 1Gbps.Side notes: 1GbE uses only a single pair to negotiate the initial connection. If a cable has only this pair working it can lead to an unresponsive NIC that seems to connect. Also, almost all new NICs can negotiate on any of the 4 pairs, thus enabling auto MDI/MDI-X (but this is not a requirement of the spec). 1000Base-T requires Cat5e cabling. 1000Base-TX simplified NICs, but required Cat6 cable; it never got off the ground for various reasons.
  • 10GbE uses PAM-16 DSQ128 coding, 833 Mbaud, 4 pairs as before. The new PAM-16 DSQ-128 with LDPC error correction is sufficiently complicated that I will not try to explain how it works here other than to say it effectively sends 3 bits of information per symbol even over cabling rated for only 500MHz (or less in some circumstances). Thus 833.3 MHz * 4 * 3b = 10Gbps.Side notes: 10GbE requires Cat6a cabling for 100m operation, Cat6 for 55m, and may work with Cat5e for very short cables. Cabling other than Cat6a should be discouraged because of the variation from the 100m standard length. Also, older NICs didn’t have the gain necessary to send 10GbE over 100m distances and were limited to shorter cables – see manufacturer for details if you have a first generation 10GbE NIC.
  • 40GbE and 100GbE have no finalized copper standards at this time. There are two 40GBase-T proposals. The first uses the same techniques as 10Gbase-T, but 4x faster, and requiring cabling certified for ~1600MHz. The second uses PAM-32 DSQ-512 and requires cabling at ~1200MHz (the higher complexity would mean relatively expensive NICs). Both are likely to use LDPC to allow the use of slightly underrated cabling.Connectors: Neither 40 nor 100GbE will use the C8P8 (colloquially RJ-45) connector, but likely a variation of it called GG45, with the 4 pairs at the 4 corners of the connector. There is also an intermediate connector, the ARJ45-HD with pins for both 10MbE-10GbE (RJ-45) and 40GbE-100GbE (GG45). TERA is a competing connector rated for 1000 MHz, it seems unlikely to become the new standard.Cabling: Cat7 and Cat7a are cabling standards rated for 600 MHz and 1200 MHz. They were originally called CatF and CatFa. Cat8.1 and Cat8.2 have been proposed with ratings for 1600 and 2000 MHz.There is some debate as to whether there will be a 100GBase-T standard as, with current technology, Cat7a, Cat8.1 and Cat8.2 will only carry such connections 10m, 30m, and 50m respective. Cat7a and up are already dramatically different cables from Cat6a and below, requiring shielding around both individual pairs and the cable as a whole. The testing that suggests these connections are possible does not demonstrate a commercially viable implementation either. There is reasonable speculation that more advanced/sensitive circuits could carry 100GbE at some point in the future, but it’s only speculation.
  • Worth mentioning: 10GBase-R, 40GBase-R, and 100GBase-R are a family of fiber specifications for 10, 40, and 100GbE which have all been standardized. These are all available in Short (-SR, 400m), Long (-LR, 10km), Extended (-ER, 40km), Proprietary (-ZR, 80km), and EPON/x (-PR/x, 20km) ranges. They all use a common 64b/66b encoding, 10.3125 GBaud, and simple use more “lanes” for additional capacity (1, 4, and 10 respectively) – lanes being different wavelengths of light on the same fiber cable. A 200GBase proprietary implementation is working it’s way to standardization, though with modulated DWDM frequencies and ranges up to 2Mm.

HOA don’t thread on me

Why would anyone in their right mind ever buy into an HOA? It’s a dystopian system that encroaches your personal liberties.

The original intent I think is to manage common grounds and ensure the neighborhood stays safe and clean, to increase the value of the property. The reality is you buy into drama and misery which reduces the value of your investment instead of protecting it.

I’ve been looking at houses, and I almost decided to buy a great house with a great view in an HOA. The trouble is its view is impacted by the fence and it’s 2 stories but the 2nd floor is not facing the view.

It took over a week to get a hold of the HOA to ask if they would consider modifications to the house to allow me to open windows to the view and adjust the height of the fence. They said no. I walked away from the house. Had they said maybe, I would have sent for review architectural schematics of the changes, waited for 45 days to get back their conditions or denial. But get this if after 45 days it’s not reviewed it’s denied automatically. There’s zero incentive for them to give you a straight answer.

My ask was not absurd. I was proposing to make changes that would bother no-one, and offered to ask approval from the neighbors first. In fact I talked to one who warned me talking to the HOA was like pulling teeth. She was bothered by them because she had 4 beautiful potted plants in front of the house and she was asked to remove them even though the CC&R allowed 4.

Who wants to put up with that **** when it’s your house and you’re trying to make it look nice. It’s not even about leaving a junk yard in front of the house.

The other aspect is you pay your torturers, and if you want to fight them you have to pay the lawyers on both sides. The papers you sign also grant the right to invade your property, to access and fix what they think is wrong, and charge you for it. Even a landlord doesn’t have that right to waltz in.

Now I mentioned that to friends and all of them came out with their horror story with HOAs. For example no AC on the window on an non air conditioned condo when it’s over 100F. Online you read stories that are appalling.

I did see an HOA that seemed nice, but it was an old neighborhood of custom built homes. The HOA had simple clear rules and the jist was make it look good and don’t do something that unsightly to the neighbors. And every month, they give prices to the nicest front yard. High end houses with a $20 HOA that’s not a nest of nazis. To arrive there, you’d have to be elected on the board, amend the CC&R, and at the same time kick out the HOA management company sucking up the HOA fees for very little service.

NO HOA for me. One close call was enough. They should not be allowed.

If you buy a house and don’t have a very conventional lifestyle where you’ll want to color something or move a rock to your liking, don’t go for HOAs. HOA houses should have a lower value than other houses because of the nagging evil stepmother that comes with that household.

Logical Fallacies list

This is just a paraphrase of this useful web page mostly for my own learning. Go read it directly.

  1. Ad hominem or Mud Slinging. Use diffamation as arguments instead of evidence in support of a conclusion. Used to discredit someone to drown the issue. “Of course you’d wear a mask you gullible germophobe!”
  2. Strawman Argument. Attacks a position the opponent doesn’t really hold and won’t defend well. It can mischaracterize the opponent’s position for the sake of deceiving others. “You’d force everyone to stay home, because you don’t care about the economy.”
  3. Argumentum ad ignorantiam or Appeal to Ignorance. Drawing conclusions from the fact something is not known. “I don’t wear a mask, because there’s no proof it works.”
  4. Either-Or, False Dichotomy, or Bifurcation. Oversimplifying to two alternatives when there are many to choose from (it could be a, b or a+b or more, porque no los dos?). Can be a manipulative tool designed to polarize, for example to strong-arming the public into supporting controversial policies. “So, would you rather wear a mask all the time, or get everyone sick?”.
  5. Slippery Slope. Go from a benign starting point and working through a number of steps to an improbable outcome. “If you don’t enforce strict stay-at home, people will go party, and everybody will die.”
  6. Petitio principii, Circular Argument. Assumes the initial argument, which is confirmed by the conclusion. “Drugs are illegal because they’re bad, that’s why they’re illegal.”
  7. Hasty Generalization. Statement without sufficient evidence to support it (illicit assumption, stereotyping, unwarranted conclusion, overstatement, exaggeration). There may not be any agreed-upon measure of sufficient proof. One or even many example is not enough to make a blanket statement. “Macs cost more than PCs”.
  8. Ignoratio Elenchi, Red Herring. A distraction from the argument, usually related to the issue but not relevant enough to be helpful. “You’ll fix unemployment? So what will you do about immigrants?”
  9. Tu Quoque, Appeal to Hypocrisy. Pointing out hypocrisy in the opponent. “I lied, but you lie too!”.
  10. Causal Fallacy. A logical breakdown when identifying the cause.
    1. false cause, non causa pro causa. Infer a conclusion without enough evidence. “LaCroix? Must be a French drink”.
    2. after this, therefore because of this, post hoc. You think it’s the cause just because it came first. “I made a wish, that’s why I’m rich now.”
    3. correlational fallacy, cum hoc ergo propter hoc. You assume two things found together are causally related. “States that don’t social distance have less cases than New York, so social distancing actually makes things worse.”
  11. Sunk Costs. You invested so much you must continue something that you would otherwise not undertake. “We’ve been dating so long, let’s make it work.”
  12. Appeal to Authority, Argumentum ad Verecundiam. Cite authorities (valid, irrelevant or false) steering away from real evidence assuming expert opinion is always correct. “Don’t wear a mask, the WHO says it’s dangerous.”
  13. Equivocation, Ambiguity. Using a word or sentence to confuse, deceive, or mislead by sounding like it says one thing but actually means another. “They want to waste taxes on wellfare, but I’ll invest in critical programs.”
  14. Appeal to Pity, Argumentum ad Misericordiam. Use emotions instead of arguments and facts. “Forgive me because I feel really bad about it.”
  15. Bandwagon. Say something is right because other people or authorities say it is or it makes you look good. Broad acceptance of something is not an indication that it is justified.
    1. ad populum, generally popular opinion.
    2. concensus gentium, opinion of authority figures.
    3. status appeal, stating an opinion that makes you look good.

Hopefully Listing these explicitly and giving them a name helps spot fallacies and become more aware of deviations in a discourse.

C++’98 reference

These are personal notes as I’ve decided to open a C++ 98 (ISO14882) reference book.

Operators

These operators can be overloaded in a class operator*(int a, int b){…}

delete delete[] new new[] xor bitand bitor compl not xor_eq and_eq or_eq not_eq and or
+ – * / % ^ & | ~ ! = < > += -= *= /= %= ^= &= |= << >> >>= <<= == != <= >= && || ++ — , ->* -> () []

Language reference

  • and a&&b (logical) or a||b xor a^b compl ~a not !a returns true/false
  • and_eq a&=b (bitwise) or_eq a|=b xor_eq a^=b performs the operation a = a&b
  • eq a==b not_eq a!=b returns true/false
  • asm  asm(“…”);
  • auto int x =2; auto y = x;
  • bitand a&b (bitwise) bitor a|b not !b
  • bool, true, false boolean values bool b = true;
  • break do/for/while/switch
  • char, wchar_t size is always 1 and stores an ASCII character symbol. wchar_t stores a UTF8 character  char c = ‘\n’; sizeof(char) ==1;
  • cast a cast is can be implicitly done by changing the type as is done in C: uint32_t u; int32_t i = (int32_t) u; . However C++ has explicit cast operators.
    • dynamic_cast<>() : polymorphic pointer cast between base / derived classes. It allows casting a base class to one of the derived classes, for example you can check is a shape object is a round object then cast it to round before passing it to methods that only accept round objects.
      class b{};
      class d: b {};
      b* bb = new d; b* bb = dynamic_cast<d*>(bb);
    • reinterpret_cast<>() allows an unsafe cast between types. Be mindful you can only cast to a stricter type alignment. You can only cast a function pointer to another function pointer. Pointer to class members can only be cast to other class members (because of *this). You can otherwise cast between pointers and integers and between any built-in types. Casting a null pointer just changes the type of the null pointer.
      char * pc; uint32_t v = reinterpret_cast<unsigned long>(pc);
    • const_cast<>() adds/removes const and volatile qualifiers
      const int i = 1; int* j = const_cast<int*>(&i); *j++;
    • static_cast<>() cast from one type to another. It keeps const and volatile qualifiers unchanged. This is a safer more explicit cast than the implicit cast and is checked at compile time.
      char c; isalpha(static_cast<unsigned char>(c));
  • catch, try, throw: void foo() { if(doit()) return; throw std::out_of_Range(“couldn’t doit”);} throws an exception method which returns void. If throw is called without an operand it re-throws the pending exception or calls terminate(). Try catches a throw to handle it if possible. try {foo();} catch(const std::exception e) { std::cerr << e.what() <<‘\n’; } catch() {std::abort();}
  • class struct private protected public this: classes default their members to private, struct to public. Private is for itself and friends. A class implicitly passes this pointer to all its non-static methods. template<T> class c { public: c(){}; protected: virtual f(){}; private: static s} c<T>::s; Private inheritance means base class public/protected members become private in the derived class: class b{}; class d: private b {}. Protected members can be used by the class, derived class and friends, using this pointer. Protected inheritance means base class public members are private for the derived class. Public members are accessible by all and represent the API of the class.
    G++: struct attribute__((packed)) {…} S; forces contiguous alignment of fields, otherwise there’s no guarantee. Also classes with virtual functions will embed a vtable at the begining changing the layout. It matters when mapping a struct to an I/O buffer.
  • virtual: class c { virtual void foo() = 0; virtual void bar(){…};} declares foo, bar and c to be polymorphic.  It means a derived class can replace the declaration of the function: class d : c {virtual void foo(){…}; virtual void bar(){c::bar();…}; }; d dd;. Declaring foo=0 means foo and c are also abstract i.e. c cannot be instantiated directly; A derived class like d must be created declaring its version of foo. d doesn’t need to re-declare its version of bar.
    An unrelated use use of virtual is to share the inheritance of a class: class d: virtual c{}; class e: virtual c{}; class f: d,e {}
  • const object can’t be modified, can’t call non const member functions. const int* p points to a const value. int* const p pointer is const but value can be changed.
  • continue do/for/while
  • delete, delete[], new, new[] allocate and free memory and calls object constructors int*p = new(123) int; printf(“%d\n”, *p); delete p; int*a= new int[10]; delete[] a;
  • double, float, long: floating point number sizeof(long double) >= sizeof(double) >= sizeof(long)
  • if else if (a!=b) {…} else {…}
  • enum enum e {a,b,c} does not support enum e : int { a=4,b,c}
  • explicit disallows type conversions calling a constructor. class c{explicit c(int x){}}; c v(1); /*ok*/ c w=v; /*fails*/;c x; x = static_cast(c)(2); /*ok*/
  • export declare an external template to compile separately from class using it export template<class T> class U { U(T x);}; export template<class T> U::U(T x) {…}
  • extern declares a class as defined/compiled in another file. Can specify the language linkage extern “C” int random(); extern const double pi;
  • for loop  for{int i=0; i < max; ++i) {…}
  • friend lets a class give a function, class or template access to its private members. class F {..} class C { friend class F; }
  • goto jump to a label in the function while(1) { if (event) goto exit;} exit: clean();. It is customary to only do goto to the end of the function, just to cleanup loose ends.
  • inline hint to tell compiler to expand the function where it was called. inline function must be defined in the same source file as it is used, before it is used. It can be defined in multiple files as long as it is the same definition (think: hpp header). inline plus(int a, int b){…} Note that large applications may have patching issues if an inline function is changed, and if all object files using it are not patched at the same time.
    Note that inlined class methods should be fully written in the hpp header.
    Note that in gcc the pragma attribute((always_inline)) is a stronger inline hint.
  • int, signed, unsigned, short, long declares and integer sizeof(long) >= sizeof(int) >= sizeof(short) >= sizeof(signed char) == 1. unsigned long should be the same size as a pointer.
    Note: it is better to use stdint.h integers like uint8_t or uint32_t.
  • mutable allows a const class to contain a data member that can be modified
  • namespace, using allows to use or set a name space. Classes define a name space that starts with the class name.
    namespace n { const it x = 123; } namespace nn = n;
    using namespace n; if (nn:x == x){…};
  • register hint the compiler the variable will be used frequently and should be in a register.
  • return returns from function, possibly a value.
    void f1() { return;} int f2(){return 0;}
  • std::size_t sizeof() returns the memory size needed to store the object or type, including padding, computed at compile time.
    int t[32]; std::size_t tSize = sizeof(t);
  • static In a class a static method doesn’t have a this pointer, and cannot access other non-static elements, static methods and variables are created once, and all objects of the class use the same one. It also can be referenced directly if it’s public.
    class C{public: static int cnt; static void foo(){…}};
    C::foo(); C::count = 0;
  • static creates at most once the object as a global object, but with internal instead of external linkage (not seen by the other elements that did not create it). Think of it as a locally visible object. A static object in a function is allocated and maintains its state across calls.
    void f() { static int callCount=0; callCount++;}
  • switch case break default implements case statements.
    switch(i) { case 1:…break; case 10:…break; default:….}
  • template declares a template, a template specialization or an instance of the template.
    template<typename T> T foo() {…};
    template<> bool foo<T>(T a){…};
    template int foo<T>(T, T);
  • typedef create a shorthand synonym for an existing type.
    typedef complexType<int,int> shortType;
  • typeid returns a reference to type_info describing the type via size_t hash_code() and const char *name(). Note typedef doesn’t create a new type_info. You can compare type_info typeid(x) == typeid(y).
    #include <typeinfo>
    template<class T> void debug(const &T t>{stc::clog<<typeid(obj).name() << ‘\n’;}
  • typename class tells the compiler the specifier is a type specifier. See templates. synonym to class here (try to use class only for classes though): template<typename C, class K> typename C::value_type foo(const C&c, const K&k) { return c+k;}
  • union aggregate struct but can only store one of the fields at a time as they are stored in the same memory location. Cannot have virtual methods, nor inherit a base class. Its members cannot be static or a reference, nor have constructors/destructors/copy-assignment operators, virtual functions or virtual base classes. A union can only initialize its first member. typedef union {int i; char c;} u; u foo[2] = {1,2}; foo.c; Unions are often used to extract bytes or bits from larger types, for example converting endianess. It works in practice, however the standard doesn’t specify how each field overlaps or aligns, so you may want to avoid that or use compiler specific pragmas: union{ uint32_t i, uint8_t __attribute__ ((packed)) c[4]}.
  • void abscence of a type, aka no parameter or return value, or a generic pointer. void foo(void) {…}; void*p =0;
  • volatile tell compiler to not do read or write optimizations. Every reference to the object will correspond to actual memory I/O. Used for objects that are modified externally such as an I/O port or a shared variable between threads. volatile sig_Atomic_t isDone = false; volatile int*port; int v; while ((v=*port) == 0){} process(v); When an element is modified by an external event you must also take into account the atomicity of your read or write operation. I/O to bytes are usually natively atomic on all platforms, but it may not be the case for int or long. See architecture specific atomic assembly instructions, locks, etc.
  • while, do performs a loop with a condition check at the begining or the end of the loop while(isTrue()){…} do{…}while(isTrue());

Preprocessor macros

Preprocessor macros are computed and resolved independently before compiling the C++ source code. This means the C++ code can use the result of the macros but not the reverse. Also macros can call each other but macro operators may not operate on macros (for example stringifying results of macros etc.).

  • # null directive, aka comment # comment
  • # stringify operator #define tostring(x) ‘[‘ #x “]:”  int val = 3; std::cout << tostring(val) << val <<‘\n’;
  • ## concat operator #define concat(x,y) x ## y std::cout << concat(val, 3) <<‘\n’;
  • #define #undef declares a macro that can be used in the code, either as an unspecified macro that now exists, a macro variable or function. #define ok or #define one 1 or #define add(a,b) (a)+(b). A macro can also be undefined. Note: it is good practice to put parenthesis around macro parameters, as their input is not processed in the macro, but the macro is just substituted in place where it’s called and operator precedence might cause grief: #define inc(a) a++.  inc(a+1) tries to compile a+1++ . It is common to protect header files to prevent them from being included multiple times with a define: foo.hpp: #ifndef FOO_HPP #define FOO_HPP …. #endif
  • defined() returns 1 if the macro name is defined. You cannot give it a macro and expect it to be expanded. For example this won’t check if foo3 is defined: #define foocat(x) foo ## x #define foo3 #if defined(foocat(3))
  • #if #elif #else #endif defines code regions that conditionally compile if the conditions are true. if and elif evaluate constant expressions #if defined(x86) … #elif defined(arm) … #else #error unsupported CPU #endif. In if/elif parameters: integers are cast to long or unsigned long; assignements are ineffective, unresolved identifiers are replaced by 0, which breaks casting, and use of sizeof, new, typeid, etc.
  • #error makes the preprocessor print an error message and abort compilation
  • #ifdef #ifdef x is shorthand for #if defined(x)
  • #ifndef shorthand for #if !defined(x)
  • #include insert a file in the code at this point. Used to include header files that declare types and functions. #include <foo.hpp> finds the header to insert from known compiler paths. #include “bar.hpp” inserts the file from the path specified (from one of the known roots).
  • #line overrides the source line number tracked by the compiler in __LINE__. Don’t use unless you create autogenerated code. You can force a line number or number and file name #line 123 or #line 123 autogen.bash
  • #pragma token give compiler directives. The syntax and semantics depend on the compiler.

Predefined macros in the C++ 98 standard:

  • __cplusplus = 199711L for C++98
  • __STDC__ == 1 for C compilers
  • __DATE__reported as const char *
  • __TIME__reported as const char *
  • __FILE__ reported as const char *
  • __LINE__ reported as a number

Templates

templates implement “parametric polymorphism”, and applies to function and class declarations and definitions.

A template has arguments that can be types, constant expressions or template references. Instantiating a template creates a specialization of a class or function for the template parameters.
template X<int i, typename T> T foo(T v) { return v+i};
std::cout << foo<3,short>(5) << ‘\n’; // prints 8.

You can also create a specialization of the template
template X<int i, char> T foo(T v) { return v[0]=i+’0′};
std::cout << foo<3,char>(“abc”) << ‘\n’; // prints “3bc”.

default arguments are OK, so is using a template parameter after it’s been defined
template<typename T, typename A = std::allocator<T>>
class C {void foo() const; }
template<typename T, typename A>
void C<T,A>::foo() {…};
Note you cannot pass a string literal to a template, you must name it first as such:
const char str[] = “msg”;
T<str> foo;

Templated template parameters are allowed if it references types from the template containing it.
template<template<class T, class A> class C, class T, class A>
void foo(C<T,A> c, T& i){..}

Function templates define a pattern for a function, and the function can be overloaded, even with non-template definitions, creating different implementations:
int min(int a, int b) {…};
template <typename T> T min(T a, T b) {..};
template <typename T, typename U> T min(T a, U b) {..};
int i = min(2,3);
short s = min<short>(2,3);
long l = min<long,short>(2,3);

STD library

Type support libraries

Concept library: C++20, ignore.
size_t, ptrdiff_t distance between 2 ptrs, NULL, size_t offsetof(struct, field) position of field. C++11: nullptr_t, max_align_t, byte enum
type_traits: C++11, Allows compile-time validation using properties of types. Useful with template arguments. if (std::is_same<int32_t, int>) {…}
limits: provides size limits std::numeric_limits<float>::max(), or std::numeric_limits<int>::digits10(). For float rounding issues see tinyness_before, epsilon, etc.
typeinfo: for runtime validation with type_info, type properties, comparisons, modifications and operations on type traits

Allocation

memory: underlying allocator for new, smart pointers like auto_ptr, atomic, align, garbage collection
new: new_handler, new, delete…
scoped_allocator: C++11.
memory_ressource: C++17.

A Task Scheduler for AVR Arduino

How would you like to decide when your code runs on your Arduino board, and do so without making your code complicated? The TaskScheduler can be the solution to run small lightweight tasks in the background while your main loop() does the non-repetitive work.

It is difficult to control repetitive tasks on Arduino because all it gives you is a single threaded loop() body function.
Beginners try usually just paste code blocks from other projects together when using different sensors/devices, in the hope to make something work, but it results in ugly if/else code that’s often poorly understood by said beginner. The Arduino forum will point you to the “how to do multiple things at the same time” post, but it’s a simple methodology that forces the programmer to explicitly keep track of time in their own variables.
The scheduler can also help experienced programmers to keep clean code: Code becomes complicated when a function handles multiple things, and having to track the timings of a task along with the task, and potentially its interactions with other tasks creates code that is unnecessarily hard to maintain. Factoring out time management will simplify the code and help make bug free code, and help developers focus on the value add for their code .

The TaskScheduler class for AVR Arduino uses the timer interrupt to schedule repetitive tasks at a specified time interval. No need for if blocks, contrived time management, nor even the need to call delay().

Here’s an example of two functions running at their own regular intervals, independently of the main loop(). Note that the library exports the nowUsec variable that is a replacement for millis().

#include <TaskScheduler.hpp>

void foo(void) {
  Serial.print(nowUsec/1000);
  Serial.println(" foo is running!");
}

void bar(void) {
  Serial.print(nowUsec/1000);
  Serial.println(" bar is running!");
}

void setup() {
  Serial.begin(9600);
}

void loop() {
  static taskScheduler task1(750, foo); // period in msec
  static taskScheduler task2(2000, bar);
  Serial.print(nowUsec/1000);
  Serial.println(" loop!");
  delay(500);
}

GitHub TaskScheduler.hpp (part of DigitalIO library)

This library will consume about 560 bytes of program memory and about 14 bytes of RAM per function to schedule, plus 8 bytes.

It has low runtime overhead: It uses the Timer0 OCCRA counter interrupt set to trigger at 1/2 period of the timer interrupt to not impact time keeping. Since Arduino already uses Timer0 for time keeping this library just piggybacks on this but uses a different interrupt vector (ISR). The ISR checks every msec if any of the registered callbacks timed out and only runs them if they do.

It defines a nowUsec global variable that can replace millis().

Gotchas and future work:

  • Functions run by the taskScheduler are run within an AVR timer interrupt handler, so they should be brief, without loops and should not expect timers to be updated.
    • Avoid using loops in them. Instead, just check the condition when the function is called, and if needed run it more often.
      Don’t write this:
      void foo() { while (! sensor.triggered()) {}; doStuff(); }
      Instead write this:
      void foo() { if (sensor.triggered()) {doStuff();} }
    • Furthermore millis() and nowUsec won’t be updated while the function is running so only check them between calls.
      Don’t write this:
      void foo() {uint32_t limit = millis()+10; while (millis() < limit ) {}; doStuff(); }
      Instead write this:
      void foo() {static uint32_t limit = 0; if (millis() >= limit) {doStuff(); limit = millis()+10;} }
  • In the near future I plan to write an additional taskScheduler that will run off the main loop() instead of from an interrupt, so the above limitations will be lifted.
    The idea is that a user will be able to simply port and combine multiple pieces of code with limited understanding of them without dealing with their scheduling.
    For example combining two basic programs may be that simple:
    program1
    void loop() { Serial.println(analogRead(pin)); delay(100); }
    program2
    void loop() { buttonState = digitalRead(buttonPin); if (buttonState == HIGH) {digitalWrite(ledPin, HIGH);} else {digitalWrite(ledPin, LOW);} delay(10);}
    merged programs
    void loop1() { Serial.println(analogRead(pin));}
    void
    loop2() { buttonState = digitalRead(buttonPin); if (buttonState == HIGH) {digitalWrite(ledPin, HIGH);} else {digitalWrite(ledPin, LOW);} }
    // Main loop
    void loop() {
    static taskScheduler task1(
    100, loop1);
    static taskScheduler task2(
    10, loop2);
    }
  • I will likely change the name of the library since DigitalIO is already claimed preventing me from adding it to the Arduino managed libraries. I will likely rename this package “ADIOS”.

If you use or like this please feel free to give a star to the project and/or comments or code enhancement requests on GitHub.

A DigitalIO class to ease Arduino I/O programming

I am writing new libraries for Arduino to get back my coding mojo after a long break!

Find the DigitalIO library on GitHub, along with its documentation, which is meant to support the multitude of sensors that report their state with a LOW/HIGH signal:
push-buttons, knock sensors, tilt switch, mercury switch, hall sensors, reed switches, rotary encoders, ultrasonic sensors

digitalsensors

I will also publish an AnalogIO library, and some for devices on buses with protocols like I2C etc as I go 🙂

But why DigitalIO?

The Arduino API provides easy methods (digitalRead() or digitalWrite()) to access I/O pins so why bother you think? Well…

  • These are slow functions, and worse, waste program memory on AVR boards. The DigitalIO library abstracts their use and allows me to replace them with AVR primitives. One of the main issues if you dig inside, is they take a pin ID and convert it to a port/bit using a table, stored in PROGMEM, which means even when you do static references (most of the time), gcc can’t optimize away all the extra code and data, and makes you access slow memory (I tried). Note the DigitalIO class uses 1 byte of DRAM.
  • They are raw access routines which do not support the different protocols of the multitude of sensors. Instead developers rely on a multitude of small libraries or code segments people reuse: A switch will set a state maybe with a noisy signal level, a knock sensor will send a brief noisy pulse, a rotary encoder a sequence of pulses on 2 lines, an ultrasonic sensor a pulse of a given duration to measure, etc. All these clutter the main code base of beginner programmer and do not help them code clear, clean programs, confusing them.

The library answers these issues, but for AVR microcontrollers also:

  • Provides asynchronous I/O management. Most users will just poll the pins busy waiting sometimes for a long time, while trying to juggle how to do multiple things to do at the same time. The library implements interrupt routines to help create event driven actions on those I/Os. For example, the rotary encoder interrupt mode allows the main routine to not have to loop on I/O changes to compute the new value of the encoder, but just reads it when it needs it, as an internal interrupt handler updates its value in memory automatically.
  • Provides timer based interrupt callbacks. This allows a user to declare a function, and schedule it repeatedly at a chosen interval with millisecond precision. Furthermore, this is implemented without impacting the Timer0 clock interrupt which would affect millis(), it uses Comparator A interrupt which is a separate vector. This means Timer 1 and 2 are still available.
  • I made an effort to make clean, well documented clear code, which can be studied by more novice programmers to practice.

Example code for the rotary encoder and a diode.
The encoder uses a class that inherits DigitalIO, so for button presses it has the same API. However it is extended to handle the rotary part.

#include <DigitalIO.hpp>

// Encoder is wired to pins 3 4 and 5, with interrupt (on pin 3).
// It returns values [-16,16] only.
// It uses encoderData to store its state (don't read it)
volatile int32_t encoderData = 0;
digitalRotaryEncoder<5,4,3, -16,16, true, encoderData> encoder;

// We have a LED on pin 13, turned off when LOW
digitalIo<13, LOW> led;

void setup() {
  Serial.begin(9600);
  led.outputMode();
}

void loop() {

  // If the encoder switch is pressed down display the value
  // We also turn on the LED
  switch(encoder.changed())
  {
  case 1:
    led.turnOn();
    const int32_t val = encoder.rotaryRead();
    Serial.print("Button pressed, position: ");
    Serial.println(val);
    break;
  case -1:
    led.turnOff();
    break;
  case 0:
    break;
  }
  delay(100);
}

(note: on Uno, only 2 digital pins support interrupts)

This is still a WIP, so I may cleanup the API more as I go.

Laser Cutter – Full Spectrum ProLF36x48

The Generator: Laser Cutter

Using the laser cutter has a few systematic things to know about worth a cheat sheet.

2020-03-02 01.55.15

Cheat sheet

Printing

  • InkSpace 1.0 is a good free vector graphic tool for your PC.
  • Import your work using a USB stick
  • Load a svg vector file into Illustrator
    • Vector lines should be 0.25pt
    • Check closely paths are not doubled (for example converted fonts)
  • Print your file, to import into the Full Spectrum app
    Note: there’s checkbox settings in Spectrum for importing vectors.

    • Verify vectors to print in vector pane
      • Select vectors and change their colors to pick separate etching properties
      • set repeats, speed and power level(s) – see swatches for setting ideas.
    • Verify raster in raster pane
  • Put material and position the head with jog controls
  • Turn on fan
  • Select print : vector / raster or both
  • Press play and stay there till it’s done, checking for fires.

Cleaning the mirror

Tools are in a blue ziplock in the white plastic box. The convex curved side of the lens is on the laser side, the concave/flat side is facing the printed material.

  • Unscrew the blower
  • Unscrew the lens assembly
  • Unscrew the lens ring with the blue taped tool, remove with hook
  • Use a cotton pad to receive the lens and a qtip to push it out with it’s gasket
  • Clean with acetone rolling the qtip on both sides of the lens.

Parts

Wrinkled Laser Printer Paper (HP Laserjet 4000/4050)

Troubleshooting laser printer issues

My laser printer was working just fine, until I had to print important papers and bam, the right side was systematically hopelessly mangled and the ink not properly stabilized there.

What to check

If your laser printer munches paper or the ink smears, it may be the fuser. So check:

  • The rollers (they’re at different locations front and back, some are plastic and slippery and a lot have grippy rubber on them to help guide the paper.
  • The fuser assembly (the teflon sleeve may be defective, have bad electrical contact or torn)

Looking online for help on the problem, every web site and HP document points out at checking for rollers jamming etc. Even though that’s a thing to check, the fuser unit is really an item that needs to be checked too. And these online helps fail to mention that.

I randomly noticed a my printer spit out a piece of brown plastic. At first I thought something got stuck, so I need to figure out how to get in there and open the path to remove the debris that’s obstructing the paper. Turns out it’s the fuser falling apart.

The fuser is made of a glass heating head, against which a roller presses, but that roller has a loose teflon sleeve around it that kinda floats there. In my case the teflon sleeve had dislodged and was slowly wandering to one side, where it was getting chewed and cut by the roller assembly. On the other side the lack of the sleeve caused the paper to jumble up and the ink to not bake properly.

Accessing the fuser

We all know how to replace the ink cartridge, but the fuser is embedded in there deep. So how do you get to it?

Well it’s also a maintenance part,  so access to it should not require you to disassemble the whole printer. Find the obvious screws to remove… or find the service manual. To find them, unclip plastic covers until you find something that looks like an access to the center or rear portion of the printer. For my HP printer I had to unclip the back plastic covers under the rear paper feeder, and expose two screws protruding by 1/2″. then I could wiggle out the metal assembly of the fuser.

An OEM repair kit will be the whole assembly, plus all the rollers of the machine, which usually are changed  at the same time. If you buy a refurb’d head it might not come with those.

An alternative is to buy a rebuild kit OR just the teflon sleeve, if that’s what failed. There’s a lot of those and only a few of the offers on ebay are for the actual HP manufactured fuser, since for most old printers they’re discontinued.

To access the teflon sleeve you’ll have to figure out how to unscrew and unclip some parts to pull the roller with the teflon. It will likely be 2 to 4 screws, maybe remove a cog, and unclip a couple of power connectors to the said roller. It may be a bit intimidating but it’s actually pretty easy. Use gloves o not leave fingerprints. It’s a 15mn job.

The teflon sleeve is bad if:

  • It’s torn
  • It’s not there (it’s a loose brown sleeve around the roller above the glass heating element)
  • It has baked ink on it (teflon’s worn and starts to stick)

I should have taken photos…

Toner issues

Your laser printer ink cartridge could be bad: it’s empty or its roller catching the ink is dirty or failing. That I don’t cover here. If the print fades, you can try to pull your cartridge and rock it side to side to even out the leftover toner.

House investment and taxes

To reduce your tax penalty you can use Prop 60 to limit your property taxes when changing homes. You can also look into 1030 exchanges to defer income tax on property gains when changing house, this has the added benefit of resetting your house deprecation schedule.

California property tax

Under California Proposition 13, property tax is assessed as 1% of the sale price (plus local tax often 0.25%?), and adjusted up max 2% yearly inflation. Major improvements are added to the assessed value but don’t trigger a full re-appraisal of the property.

In California Proposition 60 allows you to exchange your house with another of same or lower value and keep your property tax bill unchanged.

Caveats:

  • Conversion can be done only once!
  • Must be 55 or older
  • buy and sale must be within +/- 2 years.
  • House value restrictions:
    Note personal property is not counted (washer fridge hot tub…) so list it in the sale contract, and get advice from a pro. The house price must be market value based on county assessor, which might not match the actual sale price.

    • If you buy before you sell, the new house value must be <= 100% of old house
    • If you buy 0~1 year after you sell <= 105%
    • If you buy 1~2 years after you sell <= 110%
  • Houses must usually be in the same county
    • Proposition 90: Some counties may allow incoming transfers from other counties: Alameda, El Dorado, Los Angeles, Orange, San Diego, San Mateo, Santa Clara and Ventura. Do inquire about limitations and rules.
  • Resources

Federal Income tax

Exchanges

A 1031 exchange (like-kind or starker) is a way to defer taxes on a non-personal real-estate investment (aka not a primary house) and grow it tax deferred. The tax can also become long term capital gain.

  • 1031 exchanges can be done repeatedly
  • must hold property 2 years
  • like-kind is lax (apartment or land can be exchanged)
  • taxed
    • any profit cash out (boot) is taxed
    • any drop in liability (lowered mortgage loan debt) is taxed
    • deprecation recapture: when selling a building to buy land, the building, sale above deprecated value. deprecation is taxed as a gain
  • Primary house may be converted to investment then qualify for 1031
  • starker exchanges (buy after sale) are allowed with a 3-rd party escrow holding the funds
    • 45 days from close date to choose up to 3 target properties (or more if sum of their valuation is less than 200% of the property sold, or their value is 95% or more)
    • 180 days from close date to close on new property
    • Reverse exchanges (buy before sell)  are possible with similar limits
  •  Resources

Primary residence and vacation homes

If you lived 2 of the last 5 years in your residence you can shield up to 500K in profits rom taxes on the sale.

A trick is to buy a vacation home, converting it to a rental (rented more than 6 month of the year), then do a 1031 exchange for another property, and converting it to a primary residence, and later sell it with the 500K shield. The 1031 exchange is only valid if after the exchange you follow the safe harbor rules

  • the dwelling is rented out at least 14 days every year for 2 years at fair price
  • you don’t use it more than 14 days or 10% of the year

And you can get the 500K shield only if you wait 5 years from the 1031 exchange

I believe there’s a way to avoid getting the boot for deprecation, but a 1031 exchange resets the deprecation.