c++/lpt-signal-generator/lpt.cpp
changeset 45 ea8642c17495
parent 44 896eca3d40d8
child 46 616e71c2d754
     1.1 --- a/c++/lpt-signal-generator/lpt.cpp	Sun Jun 04 14:57:42 2017 +0200
     1.2 +++ b/c++/lpt-signal-generator/lpt.cpp	Sun Jun 04 14:59:13 2017 +0200
     1.3 @@ -23,35 +23,75 @@
     1.4  #include <sys/io.h>
     1.5  #include <unistd.h>
     1.6  
     1.7 +/**
     1.8 + * can not mix printf and wprintf
     1.9 + * see https://stackoverflow.com/questions/8681623/printf-and-wprintf-in-single-c-code
    1.10 + * > This is to be expected; your code is invoking undefined behavior.
    1.11 + * > Per the C standard, each FILE stream has associated with it an "orientation" (either "byte" or "wide)
    1.12 + * > which is set by the first operation performed on it, and which can be inspected with the fwide function.
    1.13 + * > Calling any function whose orientation conflicts with the orientation of the stream results in undefined behavior.
    1.14 + */
    1.15 +#include <wchar.h>
    1.16 +#include <locale.h>
    1.17 +
    1.18 +
    1.19  using namespace std;
    1.20  
    1.21 -// g++ lpt.cpp && ./a.out
    1.22 +// run this program: g++ lpt.cpp && time chrt 1 ./a.out
    1.23 +// depending to frequency and machine performance the total time will be more than given duration
    1.24 +// despite the real-time priority, because some additional time is spent in outb() functions
    1.25 +// so "duration" means total sleep time
    1.26  
    1.27  int main() {
    1.28 -  cout << "LPT!" << endl;
    1.29 +  //cout << "LPT!" << endl; // same as using printf → breaks all folllowing wprintf() calls, see note above
    1.30  
    1.31 -  //int addr = 0x378; // parport0
    1.32 +  /*
    1.33 +   * if setlocale() is missing, unicode characters are replaced with ? or „→“ with „->“ because C/POSIX locale is used, 
    1.34 +   * see man setlocale:
    1.35 +   * > On startup of the main program, the portable "C" locale is selected as default.
    1.36 +   * > If locale is an empty string, "", each part of the locale that should be modified is set according to the environment variables.
    1.37 +   */
    1.38 +  setlocale(LC_ALL,"");
    1.39  
    1.40 -  int addr = 0xe400; // parport1
    1.41 +  int addr = 0xe400; // parallel port address; first number of given port in: cat /proc/ioports | grep parport
    1.42 +  int baseFreq = 10000; // base frequency in Hz, should be between 5 000 between 10 000 Hz; lower frequency leads to dashed/dotted lines instead of greyscale
    1.43 +  int outputPower = 10; // duty cycle; 100 = 100 %
    1.44 +  int duration = 5; // in seconds; total sleep time, see note above
    1.45  
    1.46 -  //int addr = 0x278;
    1.47 +  int valueWidth =  10; // just for padding of printed values
    1.48 +  int labelWidth = -15; // just for padding of printed labels
    1.49  
    1.50 -  //int addr = 0xc800;
    1.51 +  // ' = thousand separator
    1.52 +  // * = padding
    1.53 +  wprintf(L"%*ls %*x\n",     labelWidth, L"Parallel port:", valueWidth, addr); // or %#*x – adds 0x prefix
    1.54 +  wprintf(L"%*ls %'*d Hz\n", labelWidth, L"Base frequency:", valueWidth, baseFreq);
    1.55 +  wprintf(L"%*ls %*d %%\n",  labelWidth, L"Output power:", valueWidth, outputPower);
    1.56 +  wprintf(L"%*ls %'*d s\n",  labelWidth, L"Duration:", valueWidth, duration);
    1.57  
    1.58 +  // in microseconds:
    1.59 +  int oneSecond = 1000 * 1000;
    1.60 +  int timeOn =  oneSecond *        outputPower  / 100 / baseFreq;
    1.61 +  int timeOff = oneSecond * (100 - outputPower) / 100 / baseFreq;
    1.62  
    1.63 -  if (ioperm(addr,1,1)) { fprintf(stderr, "Access denied to %x\n", addr), exit(1); }
    1.64 +  int cycleCount = duration * baseFreq;
    1.65 +  wprintf(L"%*ls %'*d ×\n", labelWidth, L"Cycle count:", valueWidth, cycleCount);
    1.66 +  wprintf(L"%*ls %'*d μs in each cycle\n", labelWidth, L"Time on:",  valueWidth, timeOn);
    1.67 +  wprintf(L"%*ls %'*d μs in each cycle\n", labelWidth, L"Time off:", valueWidth, timeOff);
    1.68  
    1.69 +  wprintf(L"%*ls %*ls\n", labelWidth, L"unicode test:", valueWidth, L"čeština → …");
    1.70  
    1.71 -  for (int i = 0; i < 30; i++) {
    1.72 -    cout << "cyklus" << endl;
    1.73 -    usleep(100*1000);
    1.74 -    outb(0b11111111, addr);
    1.75 -    usleep(10*1000);
    1.76 +
    1.77 +  if (ioperm(addr,1,1)) { fwprintf(stderr, L"Access denied to port %#x\n", addr), exit(1); }
    1.78 +
    1.79 +  outb(0b00000000, addr);
    1.80 +
    1.81 +  for (int i = 0; i < cycleCount; i++) {
    1.82 +    outb(0b00000001, addr);
    1.83 +    usleep(timeOn);
    1.84      outb(0b00000000, addr);
    1.85 +    usleep(timeOff);
    1.86    }
    1.87  
    1.88 -
    1.89 -  cout << "hotovo" << endl;
    1.90 -
    1.91 +  wprintf(L"finished\n");
    1.92  
    1.93  }