// =====================================================
// Генерация случайных чисел
//
// (C) Фролов А.В, 1997
//
// E-mail: frolov@glas.apc.org
// WWW:    http://www.glasnet.ru/~frolov
//            или
//         http://www.dials.ccas.ru/frolov
// =====================================================
#include <stdio.h>
#include <conio.h>
#include <dos.h>

void rnd_set(int bound);
int rnd_get(void);

int main(void) 
{
  int i, j;

  printf("\nГенератор случайных чисел."
    "\nНажмите любую клавишу,"
	"\nдля завершения работы нажмите <Control+C>"
	"\n");

  for(;;) 
  {
    // Устанавливаем диапазон генерации случайных
    // чисел и инициализируем таймер
    rnd_set(80);

    // Ожидаем нажатия клавиши
    getch();

    // После нажатия на клавишу получаем
    // случайное число
    j = rnd_get();

    // Выводим на экран строку символов "-",
    // длина которой равна полученному случайному числу
    for(i=0; i < j; i++) 
      putchar(219);
    printf("\n");
  }
  return 0;
}

/**
*.Name         rnd_set
*.Title        Инициализация генератора случайных чисел
*
*.Descr        Эта функция инициализирует канал 2 таймера
*              для использования в качестве генератора
*              случайных чисел
*
*.Proto        void rnd_set(int bound)
*
*.Params       int bound - верхняя граница для генерируемых
*                          случайных чисел.
**/

void rnd_set(int bound) 
{
  // Устанавливаем режим 3 для второго канала таймера
  outp(0x43, 0xb6);

  // Загружаем регистр счетчика таймера - сначала
  // младший, затем старший байты
  outp(0x42, bound & 0x00ff);
  outp(0x42, (bound &0xff00) >> 8);

  // Разрешаем работу канала
  outp(0x61, inp(0x61) | 1);
}

/**
*.Name         rnd_get
*.Title        Получение от таймера случайного числа
*
*.Descr        Эта функция получает случайное число от
*              таймера, который был предварительно
*              проинициализирован функцией rnd_set
*
*.Proto        int rnd_get(void)
*
*.Params       Отсутствуют.
*
*.Return       Случайное число в диапазоне от 0, до
*              уменьшенного на 1 значения, заданного в
*              качестве параметра функции rnd_set().
**/

int rnd_get(void) 
{
  int i;
  
  // Выдаем команду CLC для фиксирования
  // текущего значения регистра канала 2 таймера
  outp(0x43, 0x86);

  // Вводим младший и старший байты счетчика
  i = inp(0x42);
  i = (inp(0x42) << 8) + i;
  
  return(i);
}

