воскресенье, 27 декабря 2009 г.

Библиотека для семисегментного дисплея BQ-M322RD

В связи с возникшей потребностью, была написана библиотека для работы с 4-х разрядным семисегментным дисплеем BQ-M322RD разработанным компанией Bright Led Electronics. Я также уверен что данная библиотека сможет работать и с другими аналогичными 4х-разрядными дисплеями, с общим анодом.
Внешний вид дисплея


Свечение сегментов тут практически не видно, так как сьёмка проходила на ярком дневном освещении. А так, не мешало бы приложить какое-нибудь тёмное стёклышко:)
Особенности данной библиотеки
При написании использовался ассемблер. Кроме этого, пытаясь максимально сократить размер кода, использованные алгоритмы были приближены к идеалу совершенства=) Для отображения цифр на сегментах дисплея был использован способ называемый динамической индикацией. Библиотека способна реализовывать этот режим двумя способами:
  1. Используя ресурсы таймера 0
  2. Используя функцию m322_loop() которую программа должна будет непрерывно вызывать в процессе своего выполнения
Библиотека занимает 264 байт памяти программ и 13 байт памяти данных при использовании первого способа, и соответственно 240 и 13 байт при использовании второго.
Выбрать один из способов можно отредактировав файл m322/conf.h

Примеры использования

Простой пример:
/*
 программа использует библиотеку откомпилированную
 с опцией #define USE_TIMER0
*/
#include "m322/m322.h"

int main(void)
{
  m322_init(); // инициализировать семисегментный дисплей
  m322_putn(1234); // вывести число 1234
  m322_setdot(0, TRUE); // зажечь точку в разряде 0
  for (;;)
    ;
}
Если библиотека откомпилирована вторым способом, то:
#include "m322/m322.h"

int main(void)
{
  m322_init(); // инициализировать семисегментный дисплей
  m322_putn(1234); // вывести число 1234 на семисегментный дисплей
  m322_setdot(0, TRUE); // зажечь точку в разряде 0
  for (;;)
    m322_loop(80); // цикл динамической индикации
}
В данном случае добавлен вызов функции m322_loop() в бесконечный цикл, которая реализует динамическую индикацию. В качестве аргумента ей надо указать некоторое число. Частота мерцания дисплея будет зависеть от этого значения. Чем выше значение - тем меньше частота мерцания. Для моего 16мГц МК на котором я тестировал данный пример, оказалось оптимальным значение 80. Если брать больше - будет заметно мерцание, если меньше - разряды могут "поплыть".
Более интересный пример:
/*
 программа использует библиотеку откомпилированную
 с опцией #define USE_TIMER0
*/
#define F_CPU 16000000ULL /* частота работы мк (для _delay) */
#include <util/delay.h>
#include "m322/m322.h"

int main(void)
{
  m322_init(); // инициализировать семисегментный дисплей

  uint16_t number = 0;
  uint8_t n_dot = 0;
  for (;;) {
    m322_setdot(n_dot, TRUE); // зажечь точку с заданным номером
    m322_putn(number); // вывести десятичное число на индикатор
    _delay_ms(100); // пауза 100мс
    m322_setdot(n_dot, FALSE); // погасить точку с заданным номером

    if (++n_dot == 5)
      n_dot = 0;
    if (++number == 10000)
      number = 0;
  }
}
Если попробовать выполнить программу на МК, то получим - на дисплее будет отображаться число, которое будет увеличиваться каждые 100 миллисекунд, а точка "зажигаясь" будет перемещаться циклически слева-направо.
Как настроить библиотеку под себя
Перед компиляцией библиотеки необходимо задать порты к которым подключён дисплей, отредактировав файл m322/conf.h:
//
// Порты используемые для доступа к отдельным сегментам
//
#define PORT_SEGDATA  _SFR_IO_ADDR(PORTD)
#define DDR_SEGDATA   _SFR_IO_ADDR(DDRD)
/* номера пинов для каждого отдельного сегмента */
#define NPIN_DP PD7 /* точка */
#define NPIN_G  PD6
#define NPIN_F  PD5
#define NPIN_E  PD4
#define NPIN_D  PD3
#define NPIN_C  PD2
#define NPIN_B  PD1
#define NPIN_A  PD0
//
// Порты используемые для доступа к отдельным разрядам
//
#define DDR_SEGCTL    _SFR_IO_ADDR(DDRB)
#define PORT_SEGCTL   _SFR_IO_ADDR(PORTB)
/* номера пинов для каждого отдельного разряда */
#define NPIN_SEGCTL0  PB4 /* D1 */
#define NPIN_SEGCTL1  PB1 /* D2 */
#define NPIN_SEGCTL2  PB2 /* D3 */
#define NPIN_SEGCTL3  PB3 /* D4 */
//
// Дополнительные настройки
//
// заккоментируйте следующую опцию если не хотите использовать
//  ресурсы системного таймера0 для организации динамической
//  индикации семисегментного дисплея:
/* использовать таймер */
#define USE_TIMER0

#ifdef USE_TIMER0
// частота мерцания семисегментного индикатора зависит
//  от коэффициента предделителя таймера0,
// и вычисляется по формуле f = F_CPU/(P*256*4), где:
//  F_CPU - тактовая частота мк, Гц
//  P - коэффициент предделителя
/* значение предделителя для таймера */
#define TIMER0_PRESCALER ((1<<CS00)|(1<<CS01)) /* предделитель 64 */
#endif // USE_TIMER0
Я думаю здесь комментарии излишни=)

Схематическое изображение дисплея:



Полный перечень поддерживаемых функций
Библиотека поддерживает все самые необходимые функции, а именно:
  • void m322_init()
    Выполняет инициализацию семисегментного дисплея (настройка портов, таймера).
  • void m322_puthd(uint8_t c, uint8_t n)
    Выводит шестнадцатеричную цифру n в разряд с номером c индикатора.
  • void m322_puthh(uint8_t n)
    Выводит шестнадцатеричное число n в старшую часть индикатора (разряды 0 и 1)
  • void m322_puthl(uint8_t n)
    Выводит шестнадцатеричное число n в младшую часть индикатора (разряды 2 и 3)
  • void m322_setdot(uint8_t c, uint8_t b)
    Задаёт точку в разряд с номером c индикатора. Если b = TRUE - зажечь, иначе погасить.
  • void m322_putn(uint16_t n)
    Выводит на индикатор беззнаковое десятичное число n
  • void m322_loop(uint16_t n)
    Цикл для организации динамической индикации без использования таймера0
Совместимость
Думаю что библиотека будет совместима с большинством микроконтроллеров AVR серии Mega (в моём случае был использован Atmega8).

Скачать
Исходный код библиотеки вместе с примером можно скачать здесь (или здесь).

воскресенье, 6 декабря 2009 г.

Библиотека для ЖК-дисплея WH1602b

После долгой кропотливой работы изучения документации и написания кода, родилась полезная и нужная для меня библиотека для работы с этим дисплеем. Возможно она окажется полезной кому-нибудь ещё :)
О дисплее
Дисплей этот я приобрёл на молотке около года тому назад, за почти астрономическую сумму в 450рэ. Ну тем не менее он устраивает меня во всём, и в быту неприхотлив=)
Особенности этой библиотеки
Код написан на ассемблере, и очень компактен. Занимает от 298 до 466 байт в памяти программ МК. В файле конфигурации wh1602b/conf.h можно дополнительно установить поддержку следующих функций:
  • Поддержка знакогенератора (298+52 байт)
  • Поддержка функции вывода десятичных чисел (298+66 байт)
  • Поддержка функции вывода шестнадцатеричных чисел (298+72 байт)
Основные функциональные возможности
  • Вывод строк, символов
  • Вывод чисел
  • Очистка дисплея
  • Управление курсором
  • Поддержка знакогенератора (до 8-ми знаков, согласно спецификации)
  • Настройка различных параметров работы
Не поддерживается:
  • Чтение памяти дисплея
  • Текущее положение курсора нельзя определить

Библиотека использует 4-битную шину для передачи данных.

Примеры использования

Простой пример:
#include "wh1602b/wh1602b.h"

int main(void)
{
  wh1602b_init(); // инициализировать модуль, порты
  // настроить параметры управления дисплеем
  wh1602b_displayctl(DC_DISPLAY_ON); // дисплей включён
  // задать число строк
  wh1602b_funcset(FS_LINES_2); // 2 строки
  // очистить область
  wh1602b_clear();
  // вывести строку на дисплей
  wh1602b_puts("Hello, World!");

  for (;;)
    ;
}
Результат:

Следующий пример демонстрирует возможность загрузки собственного знака:
#include "wh1602b/wh1602b.h"

// собственно массив представляющий собой
//  знак который надо загрузить
static const uint8_t window_char[8] = {
  0x1f, // 1 1 1 1 1
  0x11, // 1 0 0 0 1
  0x0e, // 0 1 1 1 0
  0x04, // 0 0 1 0 0
  0x0e, // 0 1 1 1 0
  0x15, // 1 0 1 0 1
  0x15, // 1 0 1 0 1
  0x00  // 0 0 0 0 0
};

int main(void)
{
  wh1602b_init(); // инициализировать модуль, порты
  // настроить параметры управления дисплеем
  wh1602b_displayctl(DC_DISPLAY_ON); // дисплей включён
  // задать число строк
  wh1602b_funcset(FS_LINES_2); // 2 строки
  // очистить область
  wh1602b_clear();
  // записать символ ассоциировав его с кодом 5
  wh1602b_genc(5, window_char);
  // вернуться в начало (команда аналогичная move).
  //   этот вызов является обязательным после вызова genc()
  wh1602b_home();
  // вывести строку на дисплей вместе с новым знаком :)
  wh1602b_puts("Крякозябла \5");

  for (;;)
    ;
}
Результат:

В качестве аргументов для wh1602b_puts и wh1602b_genc выступает указатель на строку расположенную в области RAM. Для того чтобы иметь возможность выводить строки из памяти программ, необходимо соответственно использовать wh1602b_putsP или wh1602b_gencP. Например:
#include "wh1602b/wh1602b.h"
#include <avr/pgmspace.h>

int main(void)
{
  <...>
  // вывести строку1 из памяти программ
  wh1602b_putsP(PSTR("Здравствуй"));
  // переместить курсор на заданную позицию (нумерация с нуля)
  wh1602b_move(1,4); // 2 строка, 5 столбец
  // вывести строку2 из памяти программ
  wh1602b_putsP(PSTR("Мир!"));
  <...>
}
Результат:


Как настроить библиотеку под себя
Для начала необходимо задать порты к которым подключён дисплей. Для этого необходимо отредактировать файл wh1602b/conf.h:
#define F_CPU 16000000 /* частота мк, Гц */

#define USE_PUTN /* включить поддержку wh1602b_putn() */
#define USE_PUTH /* включить поддержку wh1602b_puth() */
#define USE_GENC /* включить поддержку wh1602b_genc() */

/* ножки к которым подключены выводы RS, RW, EN */
#define NPIN_RS PB4
#define NPIN_RW PB3
#define NPIN_EN PB2

/* порты к которым подключены выводы RS, RW, EN */
#define PORT_RS _SFR_IO_ADDR(PORTB)
#define PORT_RW _SFR_IO_ADDR(PORTB)
#define PORT_EN _SFR_IO_ADDR(PORTB)
#define DDR_RS  _SFR_IO_ADDR(DDRB)
#define DDR_RW  _SFR_IO_ADDR(DDRB)
#define DDR_EN  _SFR_IO_ADDR(DDRB)

/* ножки к которым подключены выводы DB4-DB7 */
#define NPIN_DB7  PD7
#define NPIN_DB6  PD6
#define NPIN_DB5  PD5
#define NPIN_DB4  PD4

/* порты к которым подключены выводы DB4-DB7 */
#define PORT_DB7  _SFR_IO_ADDR(PORTD)
#define PORT_DB6  _SFR_IO_ADDR(PORTD)
#define PORT_DB5  _SFR_IO_ADDR(PORTD)
#define PORT_DB4  _SFR_IO_ADDR(PORTD)
#define DDR_DB7   _SFR_IO_ADDR(DDRD)
#define DDR_DB6   _SFR_IO_ADDR(DDRD)
#define DDR_DB5   _SFR_IO_ADDR(DDRD)
#define DDR_DB4   _SFR_IO_ADDR(DDRD)

Соответствующие ножки дисплея показаны на следующем рисунке:

Как компилировать программы написанные с использованием этой библиотеки
Существует ряд особенностей при компиляции программ использующих данную библиотеку. Дело в том что ЖК-дисплей понимает только строки написанные в своём собственном варианте кодировки. Поэтому компилировать надо с ключом -fexec-charset=wh1602b. При этом, в системе должен быть установлен специальный модуль для iconv - wh1602b. Готовые скомпилированный модуль можно скачать здесь (x86_64 и i686), или собрать его самостоятельно. Для установки необходимо скопировать файл WH1602B.so в папку с модулями gconv (у меня это /usr/lib/gconv), а также отредактировать файл /usr/lib/gconv/gconv-modules, добавив строчки:
# from      to      module    cost
alias WH-1602B//     WH1602B//
alias 1602B//       WH1602B//
module  WH1602B//    INTERNAL    WH1602B    1
module  INTERNAL    WH1602B//    WH1602B    1
Самостоятельная сборка такого модуля довольно кропотливая процедура, и будет описана в следующий раз.

Полный перечень поддерживаемых функций
  • void wh1602b_init()
    Выполняет инициализацию модуля дисплея.
  • void wh1602b_funcset(uint8_t t)
    Устанавливает число строк и размера шрифта. В качестве аргументов может служить комбинация одного или нескольких параметров:
    FS_LINES_2 - использовать две строки дисплея (по умолчанию одна строка, FS_LINES_1)
    FS_FONT_5x11 - использовать шрифт размером 5х11 (по умолчанию 5х8)
  • void wh1602b_entrymode(uint8_t t)
    Настраивает режима ввода. В качестве аргументов может служит комбинация одного или нескольких параметров:
    EM_CURSOR_DIR - использовать автоматическое перемещение курсора слева-направо
    EM_DISPLAY_SHIFT - разрешить смещение дисплея
  • void wh1602b_displayctl(uint8_t t)
    Устанавливает параметры управления дисплеем. В качестве аргументов может служит комбинация одного или нескольких параметров:
    DC_DISPLAY_ON - дисплей включён (по умолчанию выключен, DC_DISPLAY_OFF)
    DC_CURSOR_BLINK - использовать мигающий курсор
    DC_CURSOR_ON - использовать курсор
  • void wh1602b_puts(const char* s)
    Выводит строку s из RAM на дисплей.
  • void wh1602b_putsP(const char* s)
    Выводит строку s из памяти программ на дисплей.
  • void wh1602b_putn(uint16_t n)
    Выводит десятичное число n на дисплей.
  • void wh1602b_puth(uint8_t w, uint16_t h)
    Выводит шестнадцатеричное число h на дисплей. Ширина поля определяется параметром w
  • void wh1602b_genc(uint8_t n, const uint8_t* p)
    Записывает знак на который указывает p в знакогенератор. Если это последний записываемый знак, и при этом ожидается вывод на дисплей, то необходимо после выполнения genc вызвать wh1602b_home() или wh1602b_move().
  • void wh1602b_home()
    Возвращает курсор в начальное положение. Если дисплей при этом смещён то функция восстанавливает его.
  • void wh1602b_move(uint8_t r, uint8_t c)
    Перемещает курсор на заданную позицию (r - строка, c - столбец). Нумерация начинается с нуля.
  • void wh1602b_putc(uint8_t c)
    Выводит символ c на экран дисплея.
  • void wh1602b_clear()
    Очищает экран дисплея.
Скачать
Исходный код библиотеки вместе с примером можно скачать здесь.

понедельник, 30 ноября 2009 г.

Пишем драйвер для лампочки=) Часть 2.

В прошлый раз я писал как создавал драйвер для лампочки. Эта часть будет посвящена тому как я использовал свой драйвер в отдельном проекте.

Написание основного проекта
Свой проект я разместил в папке ~/hard_project, основной и единственный файл которого имеет следующее содержание:
// файл ~/hard_project/libdrv/main.c
#define F_CPU 16000000UL /* тактовая частота МК */
#include "leddrv/leddrv.h"

int main(void)
{
  led_init(); // инициализация лампочки
  for (;;) // бесконечный цикл
    led_blink_ms(500); // мигнуть с частотой 0,5сек
}
Этот код настолько прост и понятен что в дополнительных комментариях и не нуждается.

Упрощённую версию Makefile для сборки проекта можно скачать тут. Скомандовав в консоли, я и получил целевой hex файл:
$ make
avr-gcc -g -Wall -O2 -mmcu=atmega168 -o .main.o -c main.c
avr-gcc -g -Wall -O2 -mmcu=atmega168  -o .main.elf .main.o -static -Lleddrv/ -lleddrv
avr-objcopy -j .text -j .data -O ihex .main.elf main.hex

А затем и прошил свой МК:
$ make program
avrdude -v -c dapa -p atmega168 -P /dev/parport0 -b 115200 -U flash:w:main.hex

И вот оно, о чудо - работает!



Итог
Всё круто! Цель достигнута. В моих планах написать аналогичные библиотеки для ЖК-модуля и датчика температуры. Надеюсь это произойдёт в недалёкой перспективе:)

---
Скачать hard_project.tar.gz

воскресенье, 29 ноября 2009 г.

Пишем драйвер для лампочки=) Часть 1.

Хочу описать собственную идею (возможно она не нова), по которой я собираюсь создавать драйверы для различных аппаратных модулей, микросхем и тп.. Базируется она на основе использования статических библиотек, которые будут подключаться к основному проекту и представлять собой драйвер для какого-нибудь отдельно взятого модуля. Статическую библиотеку предлагаю писать на ассемблере, с целью сокращения объёма кода а также получения наивысшей производительности=) Такая библиотека, подключённая к основному проекту будет занимать минимум, при этом останется больше свободного места в памяти МК для написания основной логики.

В качестве примера можно рассмотреть тривиальный пример - драйвер для лампочки (индикатора). Данный пример подходит только для демонстрации самой идеи, а не её практического применения. Лампочка уж слишком простая вещь чтобы для неё писать целый драйвер. А вообще хотелось бы написать таковые для ЖК-дисплея, микросхемы ds1307, да много чего можно ещё придумать:) Главное желание, и свободное время. С последним у меня пока проблемы... Итак, приступим!

Подготовительная часть
1) Необходимо установить в систему пакеты gcc-avr, binutils-avr, и avr-libc. (если ещё не были установлены)
2) Вкратце изучить документацию по avr-libc. Там содержится очень много интересного(:
3) Создать папку для основного проекта, у меня это ~/hard_project.
4) Создать папку для проекта библиотеки, у меня это ~/hard_project/libdrv.

Написание библиотеки
Основной файл будет иметь следующее содержание:
;; файл ~/hard_project/libdrv/leddrv.S:
#include <avr/io.h>
#include "conf.h"

.global led_init ; void led_init()
; предварительная настройка порта
led_init:
  sbi _SFR_IO_ADDR(LED_DDR),LED_NPIN ; установить ножку на вывод данных
  ret

.global led_on ; void led_on()
; включение лампочки
led_on:
  sbi _SFR_IO_ADDR(LED_PORT),LED_NPIN ; записать логическую 1 в порт
  ret

.global led_off ; void led_off()
; выключение лампочки
led_off:
  cbi _SFR_IO_ADDR(LED_PORT),LED_NPIN ; записать логический 0 в порт
  ret

.global led_blink ; void led_blink(uint16_t f)
; мигание лампочки с заданной частотой
led_blink:
  sbi _SFR_IO_ADDR(LED_PORT),LED_NPIN ; записать логическую 1 в порт
  push r24
  push r25
  rcall delay ; задержать выполнение
  cbi _SFR_IO_ADDR(LED_PORT),LED_NPIN ; записать логический 0 в порт
  pop r25
  pop r24
  rcall delay ; задержать выполнение
  ret

; задержка на заданное значение
delay: ; до 770*65535/F_CPU, сек
   clr r0
0: com r0
1: dec r0
    brne 1b
    sbiw r24,1
    brne 0b ; 770 тактов за цикл
    ret

Здесь первый параметр для функции led_blink будет передаваться через регистр r24:r25, согласно соглашениям компилятора avr-gcc. Далее, заголовочный файл будет иметь следующее содержание:
// файл ~/hard_project/libdrv/leddrv.h:
#include <stdint.h>
#ifdef F_CPU
#define led_blink_ms(x) led_blink(((x)*(uint64_t)F_CPU)/(770*1000ul))
#endif

void led_init();
void led_on();
void led_off();
void led_blink(uint16_t f);

Здесь определён макрос led_blink_ms для удобства. При его вызове нужно указывать значение в миллисекундах, в отличии от led_blink, в которой указывается значение в условных единицах =) Последний файл проекта будет иметь следующее содержание:
// файл ~/hard_project/libdrv/conf.h:
#define LED_PORT PORTC
#define LED_DDR  DDRC
#define LED_NPIN PC1

Ну здесь наверное понятно, указываются параметры порта и ножки на которой будет сидеть лампочка =)

Это всё. Теперь необходимо собрать нашу бибиотеку. Упрощённую версию Makefile для сборки проекта можно скачать тут. Скомандовав в консоли, я и получил целевой файл libleddrv.a:
$Make
avr-gcc -Wall -x assembler-with-cpp -mmcu=atmega168 -o .leddrv.o -c leddrv.S
avr-ar rcs libleddrv.a .leddrv.o

В следующий раз я покажу как использовал эту библиотеку в своём проекте=)

---
Скачать исходники libdrv.tar.gz

среда, 18 ноября 2009 г.

Программа IBCrypt v1.00

IBCrypt - программа реализующая возможность шифрования информации с использованием блочного алгоритма на основе сети Фейштеля.
С использованием IBCrypt можно зашифровывать и расшифровывать файлы, а также простые текстовые сообщения написанные во встроенном текстовом редакторе. Более подбробно сведения об алгоритме шифрования описаны в справочном руководстве. Программа является моей курсовой работой по курсу «Информационная безопасность».

  

Лицензия: GNU GPL v3. Программа написана с использованием библиотеки Qt4

Скачать (с rapidshare.de):
  • Версия для GNU/Linux, с включёнными зависимостями: (i686, amd64)
  • Пакет для Arch Linux (i686, amd64)
  • Пакет для Debian/Ubuntu (i686, amd64)
  • Версия для Windows
  • Исходный код
Скачать (с альтернативного источника):
  • Версия для GNU/Linux, с включёнными зависимостями: (i686, amd64)
  • Пакет для Arch Linux (i686, amd64)
  • Пакет для Debian/Ubuntu (i686, amd64)
  • Версия для Windows
  • Исходный код

вторник, 17 ноября 2009 г.

Этот мир сошёл с ума...

Недавно я узнал что существуют девушки которые увлекаются (да именно увлекаются!) микроконтроллерами, юниксами, и си++. При этом они внешне выглядят вполне себе симпатично, как обычные девушки..

А если представить себе такую жену? Сидишь с ней знач в одной комнате. Она за ноутом пишет операционку для 8-битного AVR... Ну а ты рядом за другим ноутом, клепаешь PKGBUILD для своей недавно написанной на Си супернавороченной проги... Общаешься с ней через жабир, типа эта - "Жена, жрать хочу, давай заканчивай там..." :-D

Всё, нет пути. Мы все скоро умрём..

Мои впечатления о Chromium..

Давно хотел сменить браузер. Долгое время использовал оперу, и меня она устраивала. Она быстро работала, и хорошо интегрировалась с KDE/Oxygen при помощи темы opera_oxygen_project. Но в последнее время стала меня раздражать своими глюками. Во-первых: почему-то стало не возможным переход по ссылке до тех пор пока страница не загрузится. В соседних вкладках происходили так же подобные артефакты. Во-вторых: иногда происходили проблемы с отображением страницы - текст за текст налазил. Ну и в третьих: если долго не чистить историю, то со временем опера начинала жутко тормозить. Кроме того, шрифты без предварительного шаманства в настройках выглядили просто ужасно. Всё это меня достало. Файрфокс хоть и хорош своей расширяемостью, он очень плохо интегрируется с KDE. Да меня бы и устраивал Konqueror, если бы не пожирал огромное количество памяти..

Поэтому, решил я попробовать Chromium от гугла. И не пожалел. Загружается за 1-2сек. на моём нетбуке Acer One. Очень лёгкий, прорисовка страниц работает очень быстро. Глюков пока не заметил. Памяти жрёт приемлемо, но не больше чем опера. Есть конечно и некоторые минусы - шрифты уж слишком размазывает (может как-то лечиться?), ну и выглядит не настолько нативно как мне хотелось бы. И ещё меня насторожила вот эта ссылка, в которой сказано что Chromium отсылает "лишнюю" информацию гуглу. В связи с этим был создан проект Iron, который является форком хромиума, и с которого удалён "плохой" код. Будем на это надеятся...


понедельник, 16 ноября 2009 г.

Программа MMixMulator

MMixMulator - симулятор компьютера MMIX. Представляет собой интегрированную среду, способную эмулировать поведение компьютера MMIX, архитектура которого описывается в книге Д. Кнута "Искусство программирования". Составляющими компонентами MMixMulator являются: компилятор ассемблера MMIX (mmixas), интерпретатор машинного кода (mmixex), и среда для разработки приложений (mmixbuger).
  • MMixBuger - среда для разработки приложений MMIX. Представляет собой программу, имеющую графический интерфейс, которая содержит редактор кода с подсветкой синтаксиса, обозреватель памяти, регистров общего и специального назначения, встроенный отладчик. С помощью данной среды, программа MMIX может быть составлена, скомпилирована и выполнена. Результат выполнения отображается в командной строке (консоли). Программа может быть отлажена по шагам, точкам останова.
  • MMixAS - ассемблер, совместимый с тем который описывается в книге Кнута (при этом некоторые фишки не поддерживаются на данный момент)
  • MMixEx - интепретатор машинного кода MMIX. Позволяет запускать программы скомпилированные при помощи MMIX-ассемблера.

Также стоит отметить, что на данный момент отсутствует поддержка инструкций с плавающей точкой, TRIP, и ещё нескольких не особо важных=) MMixMulator - это тема моего дипломного проекта. Документация находится в процессе написания присутствует.
Лицензия: GNU GPL v3. Программа написана с использованием библиотеки Qt4

Скачать:

четверг, 15 октября 2009 г.

Программа «Я Труп» v1.0!)

Однажды, холодными зимними буднями, меня попросили создать программу.. и не то чтобы просили, просто умоляли. Браться за работу я не очень то и хотел, но сжалился перед человеком, тем более что просили сделать не безвозмездно. Я был четвёртым программистом который за неё взялся, как я в последствии об этом узнал.
Работёнка предстояла сложная и для меня не привычная - надо было написать программу которая моделирует поведение устройства, конкретно устройства оперативного регулирования напряжения. Данное устройство описывалось в кандидатской работе заказчика, так что мне пришлось ещё в неё вникать. Там почти голая математика, работа с комплексными числами, многомерными матрицами, и при этом огромные по объёму расчёты которые программа должна была вычислять.
Создавалась сия програмка очень медленно, мешала учёба и основная работа в которой я работал...
В один прекрасный солнечный денёк, меня сильно обругал заказчик, и пригрозил мне сделать "ахтунг" если я не потороплюсь)) Тогда и родилось такое замечательное название к программе:) Пришлось делать..
Через два года, и с большими перерывами, работа над программой всё-таки была завершена.
О программе
Программа была написана на языке Си и Си++. Внешний вид показан на следующих рисунках:

 
Вкратце, принцип действия таков: При помощи редактора конфигурации вводятся исходные параметры системы. Затем после нажатия кнопки "Начать вычисления" происходят различные расчёты и моделирование (используя механизм псевдослучайных чисел). Результат работы сохраняется в виде отчёта в формате pdf, где содержаться различные результаты промежуточных вычислений, и графики.
Промежуточные вычисления в удобочитаемом формате, а также графики и конвертирование в pdf производятся при помощи утилит latex, gnuplot, и dvipdf, поэтому программа требует наличие в системе установленных пакетов gnuplot, texlive, и texlive-langcyrillic.
Лицензия: GNU GPL v3. Программа написана с использованием библиотеки Qt4.

Скачать (с rapidshare.de):
Скачать (с альтернативного источника):Пример генерируемого файла отчёта можно посмотреть здесь

вторник, 10 марта 2009 г.

Решение проблемы с модулем CGI::Ajax при передаче символов "+" и "%"

Наткнулся на один неприятный баг в данном модуле для Perl. Например есть вот такой код:
#!/usr/bin/perl -w
use strict;
use CGI; # or any other CGI:: form handler/decoder
use CGI::Ajax;

my $cgi = new CGI;
my $pjx = new CGI::Ajax( 'exported_func' => \&perl_func );
print $pjx->build_html( $cgi, \&Show_HTML);

sub perl_func {
 return( join("<br>",@_) );
}

sub Show_HTML {
 my $html = <<EOHTML;
 <HTML>
 <BODY>
  Enter something: 
  <input type="text" id="val">
  <input type="button" onclick='exported_func(["val"],["resultdiv"])' value="Do!"/>
  <br>
  <div id="resultdiv"></div>
 </BODY>
 </HTML>
EOHTML
 return $html;
}


Так вот, если запустить этот Perl-скрипт из браузера, ввести в поле ввода "плохую" строку вроде "text % text + text", нажать кнопку "Do!" мы не увидим знака "+" в "resultdiv".

Есть решение, в нашем примере, после строки:
 my $pjx = new CGI::Ajax( 'exported_func' => \&perl_func );

нужно добавить:
 $pjx->js_encode_function('encodeURIComponent');

В таком случае, при вводе в поле "+", мы получим "+", но если добавить/заменить "+" на "%" то ничего не получим. Кроме того, браузер выдаст различные ошибки JavaScript.

Методом копания в исходниках CGI::Ajax, была обнаружено что неполадки возникают при попытке повторного раскодирования запрошенной строки. Файл /usr/share/perl5/CGI/Ajax.pm, строка 942:

<...>
 pjxInitialized : function(){},
 pjxCompleted : function(){},
 readyState4 : function(){
  var rsp = $decodefn(this.r.responseText); /* the response from perl */
  var splitval = '__pjx__'; /* to split text */
  /* fix IE problems with undef values in an Array getting squashed*/
  rsp = rsp.replace(splitval+splitval+'g',splitval+" "+splitval);
  var data = rsp.split(splitval);

<...>

В данном куске кода строка:
  var rsp = $decodefn(this.r.responseText); /* the response from perl */
должна быть заменена на:
 var rsp = this.r.responseText; /* the response from perl */

А также в нашем примере, после строки:
 my $pjx = new CGI::Ajax( 'exported_func' => \&perl_func );

нужно добавить:
 $pjx->js_encode_function('encodeURIComponent');

И ошибка будет решена! :-)


воскресенье, 22 февраля 2009 г.

Решение проблемы неработоспособности Slax 6.х при его загрузке.

Slax имеет возможность сохранять настройки сделанные пользователем на диск. Для этого служит параметр загрузки "changes=". В таком случае, выяснилось, что при интенсивном использовании, может случится что система перестанет загружатся и станет неработоспособной. Здесь я приведу свой (возможно не самый удачный) вариант решения проблемы.

Исходные данные таковы:
Есть раздел с NTFS. Предполагается что на этот раздел должны сохранятся настройки slax. Настройки будут сохранятся в одном файле - slax.dat

Мой вариант решения проблемы это каждый раз при загрузке проверять slax.dat на ошибки и автоматически их исправлять при помощи утилиты fsck.ext2

Приступим:
1) Загружаемся в Slax, открываем консоль :)

2) Подготовим файл в котором будут хранится настройки:
# dd if=/dev/zero of=/mnt/sda1/slax.dat bs=1M count=512
# /sbin/mkfs.ext2 /mnt/sda1/slax.dat


где:
/mnt/sda1/slax.dat - место хранения файла (в моём случае он хранится на разделе NTFS)
count=512 - размер файла в мб.

3) Находим файл boot/initrd.gz на CD-ROM, копируем его в /root

4) Распаковываем
# gzip -d initrd.gz

5) Монтируем:
# mkdir fs
# mount -t ext2 initrd fs -o loop


6) Качаем пакет e2fsprogs и его зависимости. Я нашёл его в репозиториях Debian (packages.debian.org):
# wget http://ftp.de.debian.org/debian/pool/main/e/e2fsprogs/e2fsprogs_1.39+1.40-WIP-2006.11.14+dfsg-2etch1_i386.deb
# wget http://ftp.de.debian.org/debian/pool/main/e/e2fsprogs/e2fslibs_1.39+1.40-WIP-2006.11.14+dfsg-2etch1_i386.deb
# wget http://ftp.de.debian.org/debian/pool/main/e/e2fsprogs/libcomerr2_1.39+1.40-WIP-2006.11.14+dfsg-2etch1_i386.deb


Далее необходимо извлечь нужные нам файлы из .deb пакетов и положить их в initrd. Для этого нам потребуется утилита dpkg, которая существует в составе модуля "debian package tools" для Slax. Данный модуль можно скачать с сайта slax.org.

7) Собственно извлекаем:
# mkdir e2fsprogs
# dpkg --extract "e2fsprogs_1.39+1.40-WIP-2006.11.14+dfsg-2etch1_i386.deb" e2fsprogs
# cp e2fsprogs/sbin/fsck.ext2 fs/sbin
# cp e2fsprogs/sbin/e2fsck fs/sbin


# mkdir e2fslibs
# dpkg --extract "e2fslibs_1.39+1.40-WIP-2006.11.14+dfsg-2etch1_i386.deb" e2fslibs
# cp e2fslibs/lib/* fs/lib


# mkdir libcomerr2
# dpkg --extract "libcomerr2_1.39+1.40-WIP-2006.11.14+dfsg-2etch1_i386.deb" libcomerr2
# cp libcomerr2/lib/* fs/lib



8) Редактируем файл fs/linuxrc: до строки `mount_device "$CHANGESMNT" $MEMORY` прописываем:

if [ "$(basename "$CHANGESMNT" .dat)" != "$CHANGESMNT" ]; then
  /sbin/fsck.ext2 -y "$CHANGESMNT"
fi


9) Заключительные шаги: Отмонтируем наш initrd и сожмём обратно программой gzip
# umount fs
# gzip initrd


В итоге, оригинальный initrd.gz надо будет заменить полученным нами. Делается это путём перепрожига диска со Slax обновлённым initrd.gz

При дальнейшей загрузке Slax не забываем указывать параметр "changes=/slax.dat"