linuxfor 发表于 2015-1-2 16:41:48

介绍使用skill编写单位转换工具及使用自定义菜单方式调用

本人是刚学cadence的初学者,之所以从altium designer转到cadence,很大原因是被cadence中的二次开发深深吸引,下面是我学习skill编写自定义工具及菜单方式调用的例子,希望能够帮到一些初学者,少走一些弯路。
我自己装的是SPB 16.5的,如果想要查看自己装的软件版本,可以查看这里http://www.allegro-skill.com/blog-5452-411.html介绍的第一个测试函数。
参考的帖子有:http://www.allegro-skill.com/forum.php?mod=viewthread&tid=181一个简单的例子详解FORM的操作。
http://www.allegro-skill.com/forum.php?mod=viewthread&tid=45FORM编程的一般步骤。
http://www.allegro-skill.com/thread-5329-1-1.htmlSKILL调试工具设置。
参考的官方手册有:sklangref.pdf(Cadence SKILL Language Reference)介绍常用的Cadence自带的函数和algroskill.pdf(Allegro SKILL Reference)介绍Allegro下的扩展函数,用于交互式编程。
首先看下效果吧,如右图所示:



下面来创建FORM,代码如下:
; creates form
; ------------
(defun createconvform ()                                     ;定义函数createconvform()来创建FORM</p><p>drain()                                                               ;不带参数,不做任何事
convform_file = "conv.form"                              ;指定form文件名
convform = outfile(convform_file "w")                   ;打开准备写到文件的一个输出端口(文件句柄)
;form文件语言描述使用的是BNF语法,详细查看手册algroskill.pdf的第547页
;使用fprintf函数功能是将已格式化的输出写到一个端口,所以使用fprintf时需要指定端口convform
;使用skill动态创建FORM文件</p><p>;关于使用BNF format规则遵循手册algroskill.pdf的第555页所述
fprintf(convform "FILE_TYPE=FORM_DEFN VERSION=2\n");BNF 格式的规则
fprintf(convform "FORM\n")                                  ;FORM开始,与ENDFORM对应
fprintf(convform "FIXED\n")                                  ;skill只支持FIXED的FORM类型
fprintf(convform "PORT 32 6\n")                            ;FORM的宽度和高度
fprintf(convform "HEADER \"Conversion Utility\"\n") ;指定FORM的标题栏显示字符串
fprintf(convform "\n")                                           ;
fprintf(convform "TILE\n")                                     ;FORM内容开
fprintf(convform "FIELD mils\n")                           ;使用FIELD关键字定义一个域mils,用于程序的交互操作
fprintf(convform "FLOC 6 1\n")                               ;定义Field LOCation域位置:(6,1)
fprintf(convform "STRFILLIN 10 10\n")                  ;定义文本框,其宽度为10,接受的输入长度也为10
fprintf(convform "ENDFIELD\n")                              ;域mils结束定义
fprintf(convform "\n")                                          ;
fprintf(convform "TEXT \"mils \"\n")                        ;定义文本mils,\"中的\为转义字符
fprintf(convform "TLOC 20 1\n")                           ;定义Text LOCation文本位置:(20,1)
fprintf(convform "ENDTEXT\n")                              ;文本mils结束定义
fprintf(convform "FIELD mm\n")                            ;定义域mm,用于程序交互操作
fprintf(convform "FLOC 6 4\n")                              ;定义Field LOCation域位置:(6,4)
fprintf(convform "STRFILLIN 10 10\n")                   ;定义文本框,其宽度为10,接受的输入长度也为10
fprintf(convform "ENDFIELD\n")                            ;域mm结束定义
fprintf(convform "\n")                                          ;
fprintf(convform "TEXT \"mm\"\n")                     ;定义文本mm,\"中的\为转义字符
fprintf(convform "TLOC 20 4\n")                           ;定义Text LOCation文本位置:(20,4)
fprintf(convform "ENDTEXT\n")                            ;文本mm结束定义
fprintf(convform "FIELD Done\n")                         ;定义域Done,用于程序交互操作
fprintf(convform "FLOC 9 8\n")                            ;定义Field LOCation域位置:(9,8)
fprintf(convform "MENUBUTTON \"Done\" 9 3\n");定义一个宽度为9高度为3的按钮Done,
fprintf(convform "ENDFIELD\n")                           ;域Done结束定义
fprintf(convform "\n")                                       ;

fprintf(convform "\n")                                       ;
fprintf(convform "ENDTILE\n")                            ;结束TILE
fprintf(convform "\n")                                        ;
fprintf(convform "ENDFORM\n")                        ;结束FORM
close( convform)                                             ;关闭输出端口

) ;end defun createconvform
;=========================================================接着我们创建执行动作函数,代码如下; what to do on form actions
; --------------------------

(defun Conv_Action (convform)                        ;定义Conv_Action()函数来执行动作

(case convform->curField                                  ;判断当前所处域

    ("Done"                                                       ;如果是域Done,则执行这里
      axlFormClose(convform)                            ;关闭convform端口; rm may be incompatible with some platforms;命令rm可能对一些平台不兼容
; ------------------------------------------
shell("rm -f conv.form")                                 ;使用shell命令删除动态生成的conv.form文件
nil                                                               ;返回假nil
    );

    ("mils"                                                         ;如果是域mils,则执行这里
    mils=(convform->curValue)                           ;取出端口的当前值
;检查字符串mils是否匹配正则表达式模式,如果匹配则返回t ;^表示不匹配方括号里面的任意字符,+表示一个或一个以上
x = rexMatchp("[^0-9.]+" mils)                     ;测试是否出现一个或一个以上的非数字或小数点
if( eq(x t) then                                             ;如果匹配,执行then
   axlFormSetField(convform "mils" "Error")         ;将输出端口的域mils设置为字符串Error
   else                                                             ;如果不匹配,即TEXT中输入的是正确数值,执行下面的else
      mils = evalstring(mils)                              ;对字符串进行评估,即得出正确的最终的数值
   if( (mils > 393700787) then                           ;如果mils中的数值大于393700787
    mm = "Error" else                                       ;则mm中显示Error
       mm = axlMKSConvert( mils "MILS" "MM")   ;否则,调用单位数值转换函数,将mils单位数值转换成mm单位数值
    sprintf(mm "%.4f" , mm)                           ;将mm的数值制作成mm字符串
   )
   axlFormSetField(convform "mm" mm)             ;设置输出端口中对应的域mm
) ; end of if
t                                                                   ;返回真t
    );

    ("mm"                                                      ;如果是域mm,则执行这里
    mm=(convform->curValue)                        ;取出端口的当前值
x = rexMatchp("[^0-9.]+" mm)                      ;测试是否出现一个或一个以上的非数字或小数点
      if( eq(x t) then                                        ;如果匹配,执行then
            axlFormSetField(convform "mm" "Error"); 将输出端口的域mm设置为字符串Error
            else                                                   ;如果不匹配,即TEXT中输入的是正确数值,执行下面的else
      mm = evalstring(mm)                               ;对字符串进行评估,即得出正确的最终的数值
   if( (mm > 2539999) then                           ;如果mils中的数值大于2539999
    mils = "Error" else                                     ;则mils中显示Error
       mils = axlMKSConvert( mm "MM" "MILS");否则,调用单位数值转换函数,将mm单位数值转换成mils单位数值
    sprintf(mils "%.3f" , mils)                            ;将mils的数值制作成mils字符串
   )
   axlFormSetField(convform "mils" mils)         ;设置输出端口中对应的域mils
) ; end of if
    t                                                               ;返回真t
    );

); end case

); end Conv_Action
;==========================================================现在可以创建FORM,显示对应的字符串
; displays form
; -------------
(defun convertform ()                                       ;定义FORM,用于显示
;创建FORM
convform=axlFormCreate( (gensym) convform_file nil 'Conv_Action t)
axlFormDisplay(convform)                                 ;显示FORM
axlUIWPrint(convform date)                              ;打印时间

) ; end defun convertform 最后还有就是进行命令的注册,如下
; Registers conv as an 'Allegro' command
; --------------------------------------
axlCmdRegister( "conv" `conv)

将上述代码保存为conv.il文件。
1、在安装目录(%CDSROOT%)下SPB_16.5\share\local\pcb\skill中创建allegro.ilinit文件中添加下面代码:
load("conv.il")
并将上面的conv.il也保存在此目录
2、复制安装目录(%CDSROOT%)下SPB_16.5\share\pcb\text\cuimenus中的allegro.men文件到SPB_16.5\share\local\pcb\menus目录下,</p><p>编辑打开allegro.men,拉到后面文件尾,找到POPUP "&Help",并在其前面添加如下代码:
POPUP "MyT&ools"
BEGIN
       MENUITEM "&Convertion Utility", "conv"
END
添加后保存。
3、通过上面步骤之后,就可以在Allegro PCB Design XL (legacy)中点击菜单MyTools下面的Convertion Utility即可调出自定义的单位数值转换工具。
谢谢大家,如有错误,请多多提醒,改正!!

★纯属虚构♂ 发表于 2015-1-3 12:17:05

好东西 赞一个

ecoren 发表于 2015-1-6 08:42:52

好的,,,,,,,,

vivienluo 发表于 2015-1-6 09:38:35

不错。感谢分享。

stevenzhu 发表于 2015-1-6 10:09:45

不错的源码,学习了,谢谢楼主~

loney 发表于 2015-1-12 18:14:00

很好,感谢。

vivienluo 发表于 2015-1-12 21:20:05

今天仔细看了下,写得不错。相信你很快就会学会的。。。

siseob 发表于 2015-1-13 13:15:07

谢谢你的分享。

PKN1216083420 发表于 2015-1-16 14:43:33

写的真好,赞一个!

墨客的秋天 发表于 2015-12-5 19:50:37

不错的源码,学习了,谢谢楼主~
页: [1] 2
查看完整版本: 介绍使用skill编写单位转换工具及使用自定义菜单方式调用