Jump to content

    
Sign in to follow this  
Herz

Разобраться в TCL

Recommended Posts

Коллеги, есть среди нас разбирающиеся в довольно старом языке TCL?

Есть несколько коротких программ, написанных моим предшественником, и выполняющихся (время от времени) на стареньком компе под Линуксом.

Комп давно дышит на ладан, да и нет желания работать с Линуксом, по крайней мере, в ближайшее время.

Потому возникла задача переписать эти программы в скрипты МАТЛАБа, которые смогут выполнятся на других компьтерах, под Windows.

Но самому мне разобраться в написанном будет непросто. Я вообще не программист. Был бы рад, если бы кто помог с консультациями.

Share this post


Link to post
Share on other sites

Задавайте вопросы, TCL очень прост и широко используется во множестве разных средств (Xilinx Vivado, Questasim, Modelsim, OpenOCD, expect и многих других).

Проблемы на мой взгляд могут быть только при использовании каких-то нестандартных библиотек, т.к. Вы не указали что используется у вас в качестве интерпретатора TCL.

PS: TCL сам по себе кросплатформенный и поэтому возможно, что Вам поможет просто установка https://www.activestate.com/products/tcl/
PPS: Если хочется совсем бесплатный вариант - ставьте среду mingw32 под Windows и запускайте tclsh под ней.

Share this post


Link to post
Share on other sites

Спасибо. Даже не знаю, что используется в качестве интерпретатора...

Да, как вариант, установка на платформу Win подстрахует ситуацию, чтобы со смертью нынешнего железа всё не накрылось... Тут даже дело не в бесплатности.

Но, хочется разобраться и, при необходимости, вносить исправления/дополнения. Изучать для этого TCL... ну, не планировалось.

Вот пример программы:

Скрытый текст

#!/usr/bin/expect
# Accept data from RX-D2 receiver through serial port
# write out raw displacements in all three degrees of freedom 
# to stdout and to logfile
proc checkstring {str} {
   set sstr [split $str ,]
   set nb [llength $sstr]
   if {$nb != 5} {return 1}
   for {set i 0} {$i < $nb} {incr i} {
      if {[string length [lindex $sstr $i]] != 4} {return 2}
      if {[string is xdigit -strict [lindex $sstr $i]] != 1} {return 3}
   }
   return 0
}
proc hex2bin hex {
    set t [list 0 0000 1 0001 2 0010 3 0011 4 0100 \
    5 0101 6 0110 7 0111 8 1000 9 1001 \
    a 1010 b 1011 c 1100 d 1101 e 1110 f 1111 \
    A 1010 B 1011 C 1100 D 1101 E 1110 F 1111]
    regsub {^0[xX]} $hex {} hex
    return [string map -nocase $t $hex]
}
proc bin2dec {string} {
    set string [format %032s $string]
    binary scan [binary format B32 $string] I str
    return $str
}
trap {close $fidp; close $fido; close $fidl; puts "Program terminated successfully"; exit} {SIGINT SIGTERM}
set fidp [open /dev/ttyS0 r]
fconfigure $fidp -mode 9600,n,8,1 -handshake none -ttycontrol {RTS 0 DTR 0}
fconfigure $fidp -buffering line -encoding binary -translation cr
set sec [clock seconds]
set rawf "test_[clock format $sec -format %Y-%m%d%H%M -gmt T].raw"
set fido [open $rawf w]
set logf "test_[clock format $sec -format %Y-%m%d%H%M -gmt T].log"
set fidl [open $logf w]
puts $fidl "Buoy displacements measured during test at [clock format $sec -format %Y-%m%d%H%M -gmt T] GMT"
puts $fidl "Heave\tNorth\tWest"
while {1 < 2} {
  set length0 [gets $fidp buf0]
  if {$length0 == 24} {
    if {[checkstring $buf0] == 0} {
      set sbuf0 [split $buf0 ,]
      set sta [string range [lindex $sbuf0 0] 0 1]
      if {$sta == 00 || $sta == 01 || $sta == 04 || $sta == 05} {
        puts $fido $buf0
        flush $fido
        set hexz [string range $buf0 10 12]
        set hexn [string index $buf0 13][string range $buf0 15 16]
        set hexw [string range $buf0 17 18][string index $buf0 20]
        set z [bin2dec [string range [hex2bin $hexz] 1 11]]
        set n [bin2dec [string range [hex2bin $hexn] 1 11]]
        set w [bin2dec [string range [hex2bin $hexw] 1 11]]
        set sigz [string index [hex2bin $hexz] 0]
        set sign [string index [hex2bin $hexn] 0]
        set sigw [string index [hex2bin $hexw] 0]
        if {$sigz == 1} {set z -${z}cm} else {set z +${z}cm}
        if {$sign == 1} {set n -${n}cm} else {set n +${n}cm}
        if {$sigw == 1} {set w -${w}cm} else {set w +${w}cm}
        puts $fidl "$z\t$n\t$w"
        flush $fidl
        puts "$z\t$n\t$w"
      }
    }
  }
}

 

Кажется, это можно написать как-то проще и понятнее :)

А не существует ли на сегодня какого-то волшебного средства, генерирующего, скажем, тот же скрипт МАТЛАБа (или Питона), если скормить ему текст, написанный на TCL?

Вообще, приходит в голову, что были бы полезными эдакие трансляторы с языка на язык... Может, и есть?

Share this post


Link to post
Share on other sites

Используйте спойлер, это упрощает просмотр и чтение темы.

У Вас в качестве интерпретатора используется не чистый TCL, а expect. Это известное средство для автоматизации обмена с какой-либо консольной программой, которое позволяет выполнить в автоматическом режиме (скрипт на TCL) те же действия, которые обычно приходится делать в ручную. Поэтому это не в полной мере программа на TCL, а использование движка и языка TCL для решения задачи автоматизации.

В Вашем случае этот скрипт открывает первый последовательный порт (/dev/ttyS0), настраивает его и начинает выполнять обмен (приём данных) с каким-то железом используя текстовый протокол . См. строчку

set length0 [gets $fidp buf0]

Здесь переменной присваивается длина принятого текста (строки), а в переменную buf0 заносится сама принятая строка. Ниже идёт примитивный парсинг строки на TCL, анализ полученных данных и запись в raw-файл и в журнал.
Поскольку ActiveTcl поддерживает команды expect, то можно обойтись без переписывания всего и вся, а ограничиться изменением строк кода по открытию и настройке последовательного порта. Все остальное будет работать как и раньше.

См. https://docs.activestate.com/activetcl/8.6/tcl/TclCmd/open.html и особенно https://docs.activestate.com/activetcl/8.6/tcl/TclCmd/open.html#M51

Цитата
Windows
Valid values for fileName to open a serial port are of the form comX, where X is a number, generally from 1 to 9. A legacy form accepted as well is comX:. This notation only works for serial ports from 1 to 9. An attempt to open a serial port that does not exist or has a number greater than 9 will fail. An alternate form of opening serial ports is to use the filename //./comX, where X is any number that corresponds to a serial port.

Т.е. по большому счёту нужно изменить имя файла и всё должно заработать, при условии что Вы укажете правильный последовательный порт.

24 минуты назад, Herz сказал:

А не существует ли на сегодня какого-то волшебного средства, генерирующего, скажем, тот же скрипт МАТЛАБа (или Питона), если скормить ему текст, написанный на TCL?

Не думаю, что это кому-то было нужно. Во всяком случае я про такое не слышал и не верю, что такое есть.

24 минуты назад, Herz сказал:

Вообще, приходит в голову, что были бы полезными эдакие трансляторы с языка на язык... Может, и есть?

Попытки были, just for fun. Но страдания при запуске и попытке отладки сконвертированной программы ни в коей мере не компенсируют простоту такого преобразования. ;-)

Share this post


Link to post
Share on other sites

Спасибо большое! Покопаюсь дальше сам пока.

 

14 минут назад, makc сказал:

Используйте спойлер, это упрощает просмотр и чтение темы.

Да, виноват, Вы правы. Поскольку не программист, то и листинги вставлять практически не приходилось...

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this