Categories
C/C++ Ruby

用C++写ruby扩展

为了测试CDMA短信的发送方便,于是想到编译成lib,提供ruby使用。

SmsObject.h:
void SendSms(const char* msg, const char* number, char* out);

main.cpp:

//
// by deli 2009.6.11
//
#include <ruby.h>
#include "SmsObject.h"

static VALUE makepdu(VALUE self, VALUE arg1, VALUE arg2) {
    VALUE s;
    char pdu[512] = {0};
    char* msg = RSTRING(arg1)->ptr;
    char* number = RSTRING(arg2)->ptr;

    SendSms(msg, number, pdu);
    s = rb_str_new2(pdu);

    return s;
}

extern "C"
void __declspec(dllexport) Init_sms() {
    VALUE myModule = rb_define_module("CDMA");

    VALUE myClass = 
        rb_define_class_under(myModule, "SMS", rb_cObject);

    int arg_count = 2;
    rb_define_method(myClass, "makepdu", RUBY_METHOD_FUNC(makepdu), arg_count);
}

注意: C++要加上RUBY_METHOD_FUNC, C不用加。不然就会出现类似的错误:
error C2664: ‘rb_define_method’ : cannot convert parameter 3 from
‘unsigned long (unsigned long,unsigned long,unsigned long)’ to ‘unsigned long (_
_cdecl *)(…)’
None of the functions with this name in scope match the target type

test.rb:

#!/usr/bin/ruby 

require 'sms'

include CDMA

obj = SMS.new
pdu = obj.makepdu('什么都可以想,什么都可以不想,便觉得是个自由的人', '15338896034')

puts pdu

D:\Ruby\ruby-serial\sms>ruby test.rb
0000021002040702c54ce225a8d008420003200000013220c27602724487ea9f7a772b079ff86276
02724487ea9f7a772a706b079ff8627dfc4e4afcbb317a71540f53a98bb42275d00501a70801c00d
0101

大概就是这样。

Categories
CDMA

用gsmmux 测试via cdma多路复用功能

现在杭州的威盛已实现了GSM协议07.10 multiplexer。
gsmmux 可以在 developer.berlios.de/projects/gsmmux/ 上获得.按照说明安装就可以了。
代码默认用的是AT+CMUX开启功能,而CMUX在CDMA另有别用,所以他们就用VMUX来替代,在代码里,把CMUX改为VMUX,重新编译。

运行 mux,得到两个虚拟逻辑串口 /dev/mux0 /dev/mux1,
开一个终端1 cat /dev/mux0 观察数据
再开一个终端2输入 echo -e “AT\r\n” > /dev/mux0
终端1有 “OK” 响应就行了。
同样的方法测试 mux1.

核心代码在 gsm0710.c

简单说明一下。
1190 行的 main函数,读取命令行参数,
1272 行 daemonize(_debug) 设置为unix下经典后台程序,下来是设置信号中断机制。

openDevicesAndMuxMode 函数 打开modem 初始化,发 “AT+VMUX=0” 进入mux模式。

MUX启动过程
主机发: AT+VMUX=0
模块回复:OK /*进入MUX模式*/
主机发: F9033F011CF9 /*建立DLC0*/
模块回复:F9037301D7F9
主机发: F9073F01DEF9 /*建立DLC1*/
模块回复:F907730115F9
F901EF09E305070D9AF9 /*DLC1 MSC 命令*/
主机发: F90B3F0159F9 /*建立DLC2*/
模块回复:F90B730192F9
F901EF09E3050B0D9AF9 /*DLC2 MSC 命令*/

/*…开始进行MUX协议的数据传输…*/

在 1106行的openDevicesAndMuxMode,
三次(一般是三次,可以设置)打开 /dev/ptmx ,得到三对主从终端,通过符号链接,创建两个虚拟串口

/dev/mux0 /dev/mux1 这时就可以像正常访问串口一样访问它们,一般 /dev/mux0
用来专门发AT, /dev/mux1 用来发送数据业务,比如pppd 拨号上网。

数据流大概是这样的
/dev/ttyS0 <---> | /dev/pmux <----> /dev/mux0 | <----> at command
/dev/ttyS0 <---> | /dev/pmux <----> /dev/mux1 | <----> cdma pppd

下面
1162行 – 1166行
for (i = 1; i <= numOfPorts; i++)
{
sleep(1);
write_frame(i, NULL, 0, SABM | PF);
syslog(LOG_INFO, "Connecting %s to virtual channel %d on %s\n", ptsname(mux_fd[i-1]), i, serportdev);
}

write_frame(i, NULL, 0, SABM | PF); 实现的就是发
F9033F011CF9 /*建立DLC0*/
F9073F01DEF9 /*建立DLC1*/
F90B3F0159F9 /*建立DLC2*/

然后进入 while循环,用selelct 实现 i/o 多路复用,
(1)检查物理串口,如果有可读的数据,读取放到buffer,然后解析数据帧,并发送到虚拟逻辑串口
(2)检查虚拟逻辑串口,如果有可读的数据,构造数据帧,写入物理串口。

就这样,基本原理是数据分组打包与解包。

Categories
CDMA

在MTK平台上部署CDMA

原文在 2009/10/14 发表于broncho论坛,转载请写出处,谢谢!

在MTK平台上部署CDMA

[注] 我们用的MTK版本是6225 ,CDMA 模组是威盛via的。此项目没有量产,代码放在那也是加密冷藏没有价值,写思路出来与大家讨论关于程序设计。本人不是MTK专家,有分析不对之处,请指出,谢谢。

[硬件篇]
加一个cdma模组,具体操作本人不知道,就不讲述了。

[软件篇]
让我们来分析一下。既然在MTK平台,上层应用最好不要改动,就只能在底层修改。在L4层我们发现,MTK提供了mmi接口,那么我们就有机会重写这些函数,这个就是最大前提。对于CDMA,要对AT做封装,适配于L4(适配器设计模式)。我们可以开一个task,专门处理CDMA AT,串口数据的读取。考虑到CDMA的AT比较弱,特别是三方通话,呼叫保持,对AT的处理,得用较多全局变量来保存上下文。

代码目录:

代码: 全选
Vendor -|
|- ATCMD -| at_cdma
| at_gsm
| at_l4a
| at_thread

At_thread 主要是处理AT的线程.
首先创建一个task.
/* task */
void AT_Cmd_main(task_entry_struct * task_entry_ptr); 一个while 循环,处理消息。

At_gsm 是一个参考物,为了测试cdma方便,我们自己实现MTK的AT封装。At_cdma 是cdma编解码目录。可以说,at_cdma继承于at_gsm,两者有统一的接口(主要是gsm标准,cdma适应于gsm),所以很多的工作,在at_cdma做了很大的调动。如果实现和gsm不一样,我们就要rewrite接口实现,基于函数替换。

上面已有提到过,我们要重新实现mtk提供的l4a层,那么at_l4a 就是干这样的活了。为了不直接在mtk l4a的函数里修改,我们采用include 的方式。所有的处理函数放在AT_L4c_Funs_V07B.c
写我们自己的 l4a_callback_ex.c ,在ps\l4a\src\l4a_callback.c 的末尾 #include “l4a_callback_ex.c” ,然后在 l4a_main.c的 l4a_recvmsg(ilm_struct *ilm_ptr)里加以区别:如果 l4c_current_mod_id == l4c_atcmd_mod_id,就调用我们实现的接口函数处理cdma,否则,就调用mtk提供的处理gsm(不变)。

串口通讯的处理
利用w32_uart.c 里提供的一些函数,打开串口,设置波特率,数据控制流等参数。
对数据的发送,接收,加入休眠模式,以免功耗过大。

AT的处理
在MTK上对CDMA AT的处理,则采用赤裸裸的封装,源于有开发过Firebird BBS的经历,我更喜欢这种最原始的美,不要和我谈什么软件架构,设计模式的,考虑越多,项目越难以进展,领导只关心是否能跑起来,不然项目取消,大家散伙吧。说远了。AT具有随意性,我们假设发出请求的AT,就有相应的响应,设一个定时器,来处理超时问题。如果超时了,我们再发AT,如果有OK回应,就说明模组还能正常工作,那么这个AT的请求就是失败的。对自动上报的消息的处理,在获取AT响应时,我们判断是自动上报的消息,则当场处理,继续读下一行数据,直到有期望的响应值。如果请求发出一个AT, 既有自动上报消息,又有自身的请求响应,该如何处理呢?举个例子,查询网络注册情况,发出AT+CREG?后,
+CREG:1,0×3614,0x2

+CREG:1,0×3614,0x2

+CREG: 2,1,0x00C3,0x00AD

我们发现,请求的响应有4个参数,而自动上报的有三个参数。再举个例子:
开机时,模块会自动开启一个15min的计时器,如果15分钟内没有收到AT+LCT指令,模块就自动关机,如果收到了该指令,15min的计时器又重新开始计时。所以我们看到+LCT主动上报时,就发出AT+LCT。问题来了,我们打电话时,查询CLCC,那么问题出现如下:
AT+CLCC?
+LCT
AT+LCT
+CLCC:1,0,1
ok
ok

两个响应消息交错在一起,就难以分析了,我们就得保证消息串化。
等等。AT响应的处理,大部分工作是解析字符串,取出你想得到的数据,填充结构体。总之,在做AT处理时,要反复测试,考虑很多的异常,这便是软件设计的难点之一。

AT层上GSM 与CDMA的差异
就列举几个比较重要的差别,很多小细节还是非常多的,请参阅厂家的AT SPEC。
(1)AT测试命令,比如信号查询 GSM是AT+CSQ;CDMA则是 AT+CSQ? 很多种情况如此,CDMA在后面要加上一个“?”号。
(2)AT响应字符串
比如, GSM:
+CCLK: “04/01/19,15:38:32″
+CCLK:后面有空格
CDMA:
+CCLK:2008/8/6,13:57:5,3
+CCLK: 后面没有空格
响应字符串解析函数必须能处理空格问题。可以写一个类似于sscanf的函数,专用解析AT响应字符串。
(3) CDMA中”UIM”的字符串,这个主要出现在电话本与短信。MTK上是”SIM” 对应 0, “ME”对应1;CDMA把”UIM”对应为0即可。此外,短信与电话本,gsm从1开始读取,cdma则从0开始读。
(4) TE特征字符串设定
GSM: AT+CSCS
CDMA没有这方面的设定,默认为UNICODE,在电话本处理中,AT请求和响应要特别指出.
(5) 短信的PDU编解码完全不同.请参考 GSM0707与3gpp2 的C.S0015-B
(6) 电话状态查询CLCC,CDMA提供的功能很弱,不管有没有来电,拨出电话,查询CLCC总有一个+CLCC:响应,GSM则不然。CDMA处于三方通话,呼叫保持,呼叫等待时,查询CLCC也是只有一路+CLCC:响应,这样,我们得自己构建适应于GSM的CLCC,维护,更新CLCC列表。

开关机流程
(1)开机
+VPUP
模块上报开机启动标志,也可根据该命令判断模块重启,收到该命令后进行初始化设置. (模组有问题时,这个上报是不可靠的.)
+MSStatus:0
模块上报协议栈已打开。
+VROM:1
模块上报漫游状态(1 为非漫游状态)。 这个上报是不可靠的,就是说,并不是每次开机都会有这个上报。不过,如果出现这个,我们认为可以显示中国电信了,其他手机已开机就显示运营商,估计也是照这个来做。

AT+ISF?
查询模块初始化状态,2s~3s 执行一次
+ISF:1
模块初始化完成。

接下来才可以对电话本,短信,通话记录初始化。

由上,在+MSStatus:0与 +ISF:1之间,可以操作的行为有:
(0)ATE0 软件已经默认关闭回显,该步骤可省。
(1)注册网络与信号上报. AT+CREG=2 AT+ARSI=1
(2)查询UIM是否插好?AT+CPIN?
(3)查询信号 AT+CSQ?
(4)查询国家码,网络码 AT+VMCC? AT+VMNC?
(5)选择语音通道 AT+SPEAKER=0

开机流程比较繁琐,要适应与MTK的启动流程,比如开启Pin码,手机密码,网络运营商的获取,信号强度上报等。一般情况下,模块加电后会自行开启协议栈。不插UIM卡启动,模块不会自行打开协议栈。需要输入PIN的情况下,只有在用户输入正确的PIN,模块才会开启协议栈。在以上任何情形下开机,模块都会上报(+VPUP),客户可以根据此上报来判断正常使用中的模块是否重启。
(2)关机:
由于关机需要在网络上进行一些登记操作,因此正常的关机步骤是建议+CPOF关闭协议栈后延迟一段时间断电。
(3)飞行模式:
模块实现飞行模式可以直接使用+CPOF关闭协议栈,+CPON打开协议栈返回正常模式。
查询当前是否在飞行模式:+VPON.

细节:
长短信的发送:
Cdma不能无缝的发送长短信,一般要等到 +CDS:上报才能发出下一条,一般情况下,发出一条短信过4-5秒后就有+CDS上报,不过,如果发给自己的话,这个时间会更长,我们采用延时30秒。一般如果发多条短信,第二条一般会返回+CDS:2,2,66 ,就是说,发不成功。我们要把它保存起来,重发一次。

结尾
当然,要做到符合最新电信需求规范,就比较困难了。MTK本是在GSM协议上做起来的,GSM于CDMA本来就存在很大的差别。说不定过不久MTK会发布C+G的版本,啥东西人家都帮你弄好了,就等着只改界面换个图片铃声吧。

Categories
PHP

Apache+MySQL+PHP绿色集成安装包InstantRails

官方网站 http://rubyforge.org/projects/instantrails/ 是这样介绍的:
Instant Rails is a one-stop Rails runtime solution containing Ruby, Rails, Apache, and MySQL, all pre-configured and ready to run. No installer, you simply drop it into the directory of your choice and run it. It does not modify your system environment.
InstantRails是运行在Windows环境下,包括了
Apache
PHP
MySQL/PhpMyAdmin
Ruby/Rails
无疑,InstantRails本来是用来开发ruby on rails的,不过里面也集成了php,对PHPer也是
不错的选择。
  1. 下载最新的版本的压缩包.Zip, 当前版本是 2.0。
  2. 解压 InstantRails-2.0-win.zip 到 D:/InstantRails
  3. 运行 instantrails.exe.
  4. 在下一个提示框点 yes / yes ,自动配置.
到此,Apache + PHP + MySQL / PhpMyAdmin 就启动好了,很傻瓜,非常的实用。
注意: 如果要打开 gd库支持:
  1. 在 D:/InstantRails/apache. 打开php.ini
  2. 找到这一行, extension = php_gd2.dll
  3. 删除前面的分号,把注释去掉。
  4. 重启apache ,即在右下角点红色”I”字形的 InstantRails图标,点“Restart Servers”。
Categories
C/C++

用vim写c/c++程式的一些设定

—— Accelerated editing your code!

前辈们说:“一个人对Linux的熟悉程度,看他对vi的操作就知道了”。Broncho成员们都一直用这个编辑器,听说网易强行使用vim。先进的生产工具代表先进的生产力,让我们来设置一下属于自己的vim.

首先,弄一个 .vimrc 文件
一般从 /usr/share/vim/vim72/example_vimrc 拷过来用就差不多了.
$ cp /usr/share/vim/vim72/example_vimrc ~/.vimrc

然后主要就是修改配置文件 ~/.vimrc

“主题,我喜欢这个,一般要设终端是白字黑背景色.
colo desert

” 对齐与缩进
set cindent
set smartindent
set shiftwidth=4
set ts=4

” for cpp class, switch
set cino=:0g0t0(sus

” 设置行号
set nu

C/C++ 插件,这些插件都可以在vim官方网www.vim.org下载得到.
1. c-surpport 写c/c++必备
http://www.vim.org/scripts/script.php?script_id=213

” 设置leader的快捷键,原来的“\”太远了,而且位置还不固定
” leader key for c.vim
let g:C_MapLeader  = ‘,’

一些文件模板不太符合我的要求,不美观,所以我改为broncho通用的
cd ~/.vim/c-support/templates
编辑 c.comments.template
还有 Templates这个文件,定义很多宏,主要是作者,邮件,版权等等。

2. snippetsemu 代码片段
在 Vim 上使用像是 Textmate 的功能
看过Rails的demo,你一定会对那个编辑器 Textmate 很感兴趣,没错,很简单的。

svn checkout http://snippetsemu.googlecode.com/svn/trunk/ textmate
mv textmate/ ~/.vim
编辑 ~/.vimrc,填上

filetype on
filetype plugin on
set runtimepath+=~/.vim/textmate
set runtimepath+=~/.vim/textmate/after
如果装了 supertab.vim,那么Tab会冲突,解决方法:
在 ~/.vimrc 中加入
so ~/.vim/plugin/supertab.vim

3. code_complete
code_complete很不错,和SuperTab冲突 code_complete 的 tab 键可以改成其他键的,比如我就改为了Ctrl+j,和 latexSuite 一样。

关于自动补充
broncho几乎是c写的,所以一般按 Ctrl+p, 按得很happy,90%的都可以自动补充。

还有很多很多的插件与技巧,工具也不过是工具罢了,一般学会使用20%的功能,就能快速的编辑。

Pages: Prev 1 2 3 ... 12 13 14 15 16 17 18 19 20 21 22 Next