Square waves, part 2


Three years later ...

some more experiments with square wave generators.

(Actually, there must be better ways to get a short wave transmitter ...)

/*
 * generate high frequencies 
 *          pros                             cons
 *          ----------------------------     -----------------------------
 * out01:   F_CPU / 4                        duty cycle 33 %   
 * inc:     duty cycle 50 %                  F_CPU / 8, also modifies the 7 higher bits 
 * toggle:  duty cycle 50 %, ~ F_CPU / 4     jitter after 2^n cycles
 * out01M:  cuty cycle 50 %, ~ F_CPU / 2     jitter after 2^n cycles
 * Output pin is d8, PORT B, bit 0 on Arduino UNO
 * PORTB address = 5
 * PINB  address = 3 (for toggle)
 */

const byte out01  = B00100000;  // jumper d6-d7
const byte inc    = B10000000;  // jumper d4-d5
const byte toggle = B10100000;  // no jumper
const byte out01M = B00000000;  // jumper d4-d5 and d6-d7
// press reset after changing the jumpers

/* * MACRO D doubles the argument, can be cascaded * (exponentiate is easy but multiply is not) */
#define D(X) X X
#define TOGGLE asm("sbi 3,0"); 
#define OUT01M PORTB = b; PORTB = 0;

void setup() {
  pinMode(4,OUTPUT);
  pinMode(5,INPUT_PULLUP);
  pinMode(6,OUTPUT);
  pinMode(7,INPUT_PULLUP);
  pinMode(8,OUTPUT);
  byte mode = PIND & B10100000;
  Serial.begin(9600);
  Serial.println(F(__FILE__));
  Serial.println(mode,BIN);
  delay(110); // only to perform the print command before cli
  cli();
  switch (mode) {
// each function runs indefinitely, so no breaks are required
    case out01:  OUT01();
    case inc:    INC();
    case toggle: TOGGLE1();
    case out01M: OUT01R();
  }
}

void OUT01() {
  byte b = 1;
  while (true) {
    PORTB = b;
    PORTB = 0;
  }  
/* --> 4.003.634 Hz, duty cycle: 1 / 3
 10a: 81 e0         ldi r24, 0x01 ; 1                          1 clock
LABEL  10c: 85 b9         out 0x05, r24 ; 5                          1 clock
 10e: 15 b8         out 0x05, r1  ; 5                          1 clock
 110: fd cf         rjmp  .-6       ; 0x10c <_Z5OUT01v+0x2>    2 clocks 
                                                       sum     4 clocks for up and down */
}

void INC() {
  byte b;
  while (true) {
    b++;
    PORTB = b;
  }
/* --> 2.001.814 Hz, duty cycle: 1 / 2 
 112: 8f 5f         subi  r24, 0xFF ; 255                      1 clock (the INC instruction also takes 1 clock 
 114: 85 b9         out 0x05, r24 ; 5                          1 clock
 116: fd cf         rjmp  .-6       ; 0x112 <_Z3INCv>          2 clocks
                                                       sum     4 clocks for up or down */
}

void TOGGLE1() {
  while (true) {
    D(D(D(D(D(D(D(TOGGLE)))))))
  }
/* --> 3.972.565 Hz, duty cycle: 1 / 2
 118: 18 9a         sbi 0x03, 0 ; 3                            2 clocks for up or down
 11a: 18 9a         sbi 0x03, 0 ; 3
...
 614: 18 9a         sbi 0x03, 0 ; 3
 616: 18 9a         sbi 0x03, 0 ; 3
 618: 7f cd         rjmp  .-1282    ; 0x118 <_Z7TOGGLE1v> */
}

void OUT01R() {
  const byte b = 1;
  while (true) {
    D(D(D(D(D(D(D(OUT01M)))))))
  }
/* --> 7.945.124 Hz, duty cycle 1 / 2  *   
 21c: 85 b9         out 0x05, r24 ; 5
 21e: 15 b8         out 0x05, r1  ; 5
 ...
 418: 85 b9         out 0x05, r24 ; 5
 41a: 15 b8         out 0x05, r1  ; 5
 41c: ff ce         rjmp  .-514     ; 0x21c <_Z6OUT01Rv+0x2> */
}

void loop() { }





contact: nji(at)gmx.de