28 Kasım 2016 Pazartesi

HDLC (High Level Data Link Control) protokolü

HDLC ve Hava Kuvvetlerimiz
Hava Kuvvetlerinin elindeki bir çok radar mesajlaşırken HDLC ( (High Level Data Link Control) protokolünü kullanıyor. "Radar Ağı" (Radnet) projesinde HDLC protokolünü kullanan Radar Message Conversion Computer (RMCC) (Türkçesi : Radar Mesaj Çevirim Bilgisayarı) bilgisayarını kullanılmakta.

HDLC bir Layer 2 (yani Data Link) protokolü. Layer 2 protokoller aynı LAN içindeki iki cihaz arasında paketlerin hatasız olarak aktarılmasını sağlar. Örneğin LAN içindeki Layer 2 protokolü Ethernet protokolüdür.

Bu protokolü bilmeden rahatça mesajlaşabilmek için "MicroGate" firmasının "Synclink GT4" kartı kullanılırsa bu kart aldığı/verdiği mesajları HDLC protokolüne çeviriyor ve programlama yükünü azaltıyor.

Kartın 2 veya 4 RS-232 portu modeme bağlanarak radarla mesajlaşma yapılıyor.

HDLC ve Frame
HDLC protokolünde frame ayracı olarak 0x7E kullanılıyor. Aşağıdaki şekilde bunu görmek mümkün. Ethernet'te alışageldiğimiz MAC adresleri HDLC'de bulunmuyor.

  
HDLC ve Diğer Uygulamaları
HDLC protokolünün diğer başka platformlarda da kullanıldığını göstermek için aşağıdaki resmi buradan aldım. Örnekte de görüldüğü gibi sonar HDLC ile TACTICOS Savaş Yönetim Sistemine bağlanmış.



22 Kasım 2016 Salı

Jenkins New Job

Giriş
Yeni bir proje açmak istersek New Job menüsüne tıklarız. Jenkins'in kendine ait bir Yapılandırma Sistemi (Build System) yoktur. Harici bir yapılandırma sistemini tetikler ve her yapılandırmayı organize ederek derli toplu bir şekilde erişilebilir kılar.

Yeni bir proje açarken karşımıza çıkan seçeneklerle ilgili notlarım aşağıda.

Advanced Project Options 
Açıklama yaz.

Source Code Management
Kodu nereden çekeceğimizi gösterir.

SVN için şöyle yaparız
Repository URL = http://...
Credentials = ...
Local Module Directory = ./Code veya .
Repository depth = Infinity
Check-out Strategy = Use 'svn update' as much as possible.

girilebilir.


Build Triggers Başlığı 
Build Triggers için hiç bir şey seçilmezse proje sadece elle tıklanarak build eder. Release vermek üzere bu yöntem kullanılabilir.

Build periodically Kutusu
Schedule alanına @midnight girilebilir


Build Başlığı 

Execute Shell Kutusu
Execute Shell Kutusu yazısına taşıdım

SLOCCount Plugin
Jenkins Pluginler yazısına taşıdım



21 Kasım 2016 Pazartesi

Stanag 4539

Giriş 
Tam adı "Stanag 4539 Technical Standards For Non-Hopping HF Communication Waveforms". Yani frekans atlamalı olmayan HF için kullanilan bir standart. Kökeni Amerikan ordusunun kullandığı MIL-STD 188-110' a dayanıyor.

Askeri denizcilikte en revaçta olan standart. 9600 bps'e kadar çıkabilir. İçinde bir sürü dalga şekli tanımlı.

Çok kullanılan bir dalga şekli 9600 US.

Annex D
Annex D'de 3 tane TDMA dalga şekli tanımlı. Bunlar WaveForm 1, WaveForm 2, WaveForm 3 gibi ve Link 22'de kullanılıyorlar.
TDMA dalga şeklinde N tane Media Codec Frame (minislot) vardır. N - 1 tane MCF veri gönderme için kullanılır. Seçilen dalga şekline göre kaç bit gönderilebileceği bellidir.


Senkron Seri Kart (SSC)

Giriş
Modemler senkron veya asenkron çalışabilirler. Senkron modemlerle iletişim çok daha hızlıdır.
Bunun sebebi asenkron iletişimde Universal Asynchronous Receiver Transmitter (UART) kullanılırken, senkron iletişimde Universal Synchronous Asynchronous Receiver Transmitter (USART) kullanılması.

USART kendi içinde clock içerdiği için start/stop bitlerine ihtiyaç duymaz.

RapidM SSC
Modemle senkron iletişim için kullandığımız cihaz "Rapidm Synchronous Serial Card".

Slot Girişi
Bu kart bilgisayarın PCI Slot girişine takılıyor. DCE arayüzü (DB 25 male) senkron modda çalışıyor.
115200 baud'a kadar hız sağlayabiliyor.

Bağlantı Şekli
Bağlantı şekli şöyle
SSC <-> Kripto <-> Modem <-> Telsiz
Sürücü
Sürücü kurulduktan sonra sisteme iki tane yeni cihaz ekleniyor.
/dev/rmssc_uart0 : Telsizi kontrol etmek için kullanılır
/dev/rmssc_usart 0 : Modemle veri iletişimi içindir. Senkron veya asenkron çalışabilir. Asenkron çalışması /dev/ttyS0 ile aynıdır.

Programlama
Cihaz sürücüsü kurulduktan sonra Linux'ta termios programlanır gibi kullanılıyor. Yani
1. open (...)
2. ioctl (...)
3. select (...)
4. write (...)
5. read (...)
6. close (...)
şeklinde programlanır.

Kendi sürücüsüne mahsus ayarlar usartconf.h dosyasında

Pinler
Hardware Flow Control
Ya RTS/CTS ya da DTR/DSR seçilmeli.

Pinleri şöyle:

RTS ve CTS  Pin 4 ve 5
Hardware flow control için kullanılır. CTS pininin durumu sorgulanabilir.

DSR (Data Set Ready) - Pin 6
Hardware flow control için kullanılır. DSR pininin durumu sorgulanabilir.

DCD (Data Carrier Detect) -  Pin 8
Karşıda modem varsa bu pine elektrik verir. DCD pininin durumu sorgulanabilir.

DTR (Data Terminal Ready) - Pin 20
Bilgisayar açılınca bu pine elektrik verir. Bu pin aynı zamanda hardware flow control için de kullanılır. DTR pininin durumu sorgulanabilir.

RapidM8
Bu modem kendi üzerindeki (internal) veya SCC üzerindeki saati (clock) kullanabilir. Cihazın 3 modu var

Senkron : Sadece verilen veriyi havaya gönderir. (Over the air - OTA)
Hi-Speed Asynchronous : Sadece verilen veriyi havaya gönderir
Asynchronous : Start , Character, Parity ve Stop bitlerini havaya gönderir.


İki Audio Çıkışı
RM8 modemde 2 audio çıkışı var. Bunlar Single Side Band telsizlerde 2 tane 3Khz bant kullanıp hızı artırmaya yarar.

Modem'de Interleaving
Interleaving verinin arasına bir şeyler ekleme anlamına gelir. Modem göndereceği veriyi bloklara böler. Her bloktan biraz biraz gönderir. Yani bloklar içiçe girmiş gibi olur. Böylece bir anda meydana gelebilecek sinyal bozulması her bloğu biraz etkiler. Bloktaki verinin kurtarılabilme imkanı artar.

HF Telsiz
2Mhz - 30 Mhz arasındadır. İki dalga şekli kullanır. Gökdalga (sky wave) ve yer dalga (ground wave). Yerdalganın menzili 100 deniz mili civarındadır. Gökdalganın menzili 1000 deniz miline kadar çıkabiliyor ancak iyonosferin durumuna çok bağlı. 1 saat önce iletişim kurulabilen bir istasyonla, iyonesferdeki değişiklikten dolayı iletişim kurulamayabilir.

RapidM8 Stanag 4285 , Stanag 4529 ve Stanag 4539 dalga şekillerini destekler.

Stanag 4539 HF için. Non hopping yani frekans atlamaliı değil. Kökeni Amerikan ordusunun kullandığı MIL-STD 188-110' a dayanıyor. Askeri denizcilikte en revaçta olan standart. 9600 bps'e kadar çıkabilir. İçinde bir sürü dalga şekli tanımlı. Anex D'de 3 tane TDMA dalga şekli tanımlı. Bunlar WaveForm 1, WaveForm 2, WaveForm 3 gibi ve Link 22'de kullanılıyorlar. TDMA dalga şeklinde N tane Media Codec Frame (minislot) vardır. N - 1 tanesi MDC veri gönderme için kullanılır. Seçilen dalga şekline göre kaç bit gönderilebileceği bellidir.

Kullandığımız dalga şekli ekranda şöyle görülür.
12 KHz VHF-1 48.0K C US (Coded Ultra Short)
Sağ tarafta TX-15 RX-19 dbm ile seviyler görülebilir.

ALE : Automatic Link Establishment Stanag 4538'de tanımlı. Modem, iletişim kalitesine göre, hıza göre frekans ayarlaması yapabilir. RapidM8'de ALE yeteneği var.


UHF Telsiz
Veri muhabere için tanımlı tek Stanag 4691 Anex B içinde.. Genelde ses (AM/FM) ve veri linki (Link 11, Link 22) için kullanılır. 225 Mhz - 3 Ghz arasındadır. 225 Mhz - 400 Mhz askeri denizcilik içindir.

VHF
Genelde kara kuvvetleri kullanır

16 Kasım 2016 Çarşamba

VirtualAlloc metodu

Giriş
Açıklaması şöyle
This function allows you to specify additional options for memory allocation. But it allocates memory in large page with a minimum indicated by GetLargePageMinimum, you can commit, reserve with it. It's not for general use. Memory allocated by this function is automatically initialized to zero.
Parametre için açıklaması şöyle
The VirtualAlloc() will allocate a virtual memory page that have some attributes (by the parameter "fdwProtect").



10 Kasım 2016 Perşembe

Jitter

Giriş
Açıklaması şöyle
Network jitter is the deviation in time for periodic arrival of data.

Türkçe 'si titreme, segirme sanırım. Belli bir zamanda olması gereken işin zaman ekseninde biraz kayarak erken veya geç olması jitter 'dır. Jitter'ın düşük bir değer olması makbüldür.

Jitter , Latency'den (gecikme) farklıdır. Latency bir paketin, sinyalin kaynaktan hedefe varması için gereken süredir. 

Built In Test (BIT) yöntemleri

Giriş
BIT Türkçe 'ye Cihaz İçi Test (CİT) olarak çevriliyor.

Cihaz üreticileri genellikle standartları takip etmezler. Bir çok cihazın bir araya geldiği bir sistemde hepsine BIT testi yapan kodu yazmak bazen kolay olmuyor. Aşağıda konuyla ilgili bazı notlarım var.

Öncelikle her cihaz için ortak olan metodları bir arayüze toplamak gerekir. Bu arayüze IDevice diyelim.
interface IDevice
{
    void PerformBIT();
    int GetBITResult();
}

Daha sonra istisnai durum yaratan cihaz için bir başka arayüz tanımlayalım.
interface INewDevice : IDevice
{
    bool CheckPBIT();
}


7 Kasım 2016 Pazartesi

perror metodu

Giriş
errno değişkenine atanan hat kodunu stderr akımına metin olarak yazar.

Orientation
Açıklaması şöyle
The perror() function shall not change the orientation of the standard error stream.
Wide-oriented
Şöyle yaparız.
#include <stdio.h>
#include <wchar.h>
#include <errno.h>
int main(void)
{
  fwide(stderr, 1);
  errno = EINVAL;
  perror("");
  int x = fwide(stderr, 0);
  printf("fwide: %d\n",x);
  return 0;
}
Multibyte -oriented
Şöyle yaparız.
#include <stdio.h>
#include <wchar.h>
#include <errno.h>
int main(void)
{
  fwide(stderr, -1);
  errno = EINVAL;
  perror("");
  int x = fwide(stderr, 0);
  printf("fwide: %d\n",x);
  return 0;
}
Byte oriented
Şöyle yaparız.
#include <stdio.h>
#include <wchar.h>
#include <errno.h>
int main(void)
{
  printf("initial fwide: %d\n", fwide(stderr, 0));
  errno = EINVAL;
  perror("");
  int x = fwide(stderr, 0);
  printf("fwide: %d\n", x);
  return 0;
}


2 Kasım 2016 Çarşamba

rand_r metodu

Giriş
Bu metod POSIX.1-2008 ile obsolete olmuştur ! Yeni kodlarda kullanmamak gerekir.

1. C'deki rand() metodunun tersine bu metod state verisini seed için verilen alanda saklar.

2. Normalde thread-safe değildir. Eğer her thread kendi seed bellek alanını sağlarsa bu metod thread-safe olarak kullanılabilir. Bu metod global state ile kullanılırsa thread-safe olmaz!

Örnek 1
rand() çağrısını kolayca myrand() ile değiştirmek istersek şöyle yaparız.
int myrand()
{
  static unsigned int myseed = ... some initialization of your choice ...;
  return rand_r (&myseed);
}
Örnek 2
Şöyle yaparız.
unsigned int seed = YOUR_INITIAL_SEED;

for (int x = 0; x < 100000; x++)
{
  unsigned int r = rand_r(&seed);
  ...
}

1 Kasım 2016 Salı

popen ve _popen metodları

Giriş
Şu satır dahil edilir.
#include <stdio.h>
popen metodu
Çalıştırılan uygulamanın ya stdout veya stdin akımını alır. sterr akımını kullanmaz!

İmzası
İmzası şöyledir.
FILE *popen(const char *command, const char *type);
type alanına "r" veya "w" karakteri gelir. Açıklaması şöyle
The type argument is a pointer to a null-terminated string which must contain either the letter 'r' for reading or the letter 'w' for writing.
POSIX dokümanında da benzer yazı mevcut. Açıklaması şöyle
The character 'b' shall have no effect, but is allowed for ISO C standard conformance.
Okumak İçin
Şöyle yaparız.
FILE* pipe = popen("...", "r");
Şu kod hatalı. Çünkü okuma akımı zaten binary açılır.
FILE* pipe = popen("...", "rb");
Hata Yakalama
Eğer olmayan bir komut çalıştırılmaya çalışılırsa FILE* null dönmüyor. Bu durumda ne yapmak lazım bilmiyorum.

popen kabuğu kullanır
popen() çağrısı std::system() çağrısına benzer şekilde alt tarafta fork() ile yeni bir child process oluşturuluyor ve child içinde yine aynı şekilde

execl(_PATH_BSHELL, "sh", "-c", program, NULL);

çağırılıyor. Ancak arada fark olarak child process yaratılmadan önce bir pipe oluşturuluyor.

int pdes[2];
pipe(pdes);

popen "r" ile çağrılmışsa child process çalışmaya başladıktan sonra yaratılmış olan pipe'ın okuma ucu STDOUT_FILENO ile yer değiştiriyor.

close(pdes[0]);//Pipe'ın okuma ucunu kapat
(void)dup2(pdes[1], STDOUT_FILENO);//Pipe'ın yazma ucu stdout ile aynı olsun
(void)close(pdes[1]);//Pipe'ın yazma ucunu da kapat


Bu işlemin ardından çağırılan execl() ile çalıştırılan shell output stream olarak yaratılan pipe'a yazdığı için parent process'te child'ın çıktısını okuyabiliyor.

Burada dikkat edilmesi gereken nokta çalıştırılan uygulamanın ya stdin veya stdout akımının kullanılması, stderr akımı kullanılmıyor. Hepsini birden kullanmak için buraya bakabilirsiniz.

Örnekler
Kendi script'imi çalıştırmak için şöyle yaparız.
#include <iostream>
#include <stdio.h>

using namespace std;

int main() 
{

    FILE *in;
    char buff[512];

    if(!(in = popen("my_script_from_command_line", "r"))){
        return 1;
    }

    while(fgets(buff, sizeof(buff), in)!=NULL){
          cout << buff; // here you have each line 
                        // of the output of your script in buff
    }
    pclose(in);

    return 0;
}
ls uygulamasını çalıştırmak için şöyle yaparız.

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

int main() {
    FILE *process;
    char buff[1024];

    process = popen("ls -l", "r");

    if (process != NULL) {
        while (!feof(process)) {
            fgets(buff, sizeof(buff), process);
            printf("%s", buff);
        }

        pclose(process);
    }

    return 0;
}
bash komutu çalıştırmak için şöyle yaparız.
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

int main ()
{
    // get PATH using pipe
    FILE* pip = popen("exec bash -c 'echo $PATH'", "r");
    if (!pip)
    {
        printf("can not open pipe!");
        return 1;
    }

    char lineversion[600];
    memset (lineversion, 0, sizeof(lineversion));
    if (!fgets(lineversion, sizeof(lineversion), pip))
    {
        printf("fgets error!");
        return 1;
    }

    std::cout << lineversion << std::endl;

    // get PATH using getenv
    char* pPath = getenv ("PATH");
    std::cout << pPath << std::endl;
}
_popen ve _pclose
Bu metod Windows'taki C kütüphanesinde bulunur. popen() ile hemen hemen aynıdır. Şöyle yaparız.
const std::string command = ...;
FILE* output = _popen(command.c_str(), "r");
...
_pclose(output);
pclose metodu
İşlem bitince FILE* pclose() ile kapatılmalıdır.